Java零基础讲解异常

目录
  • 什么是异常?
  • 异常的处理
  • 异常的抛出
  • 处理异常
    • throws声明异常
    • 捕获异常
    • finally:
  • 异常的处理流程
  • 自定义异常

什么是异常?

异常在我们写代码是特别常见,因为程序员大部分时间都在修复bug,在java中通过throwable顶层类又可以分为两个,一个是Error(错误),一个是Exception(异常)。

Error(错误) : Error与异常不同的是,错误并不能处理,而是程序员造成的问题,比如语法错误那就要程序员检查自己的语法,比如结果错误(StackOverflowError和OutOfMemoryError

),那就要程序员检查自己的逻辑。

Exception(异常) : 这个可以通过一些方式来处理,比如我们后面要讲的throws(声明异常),try{}catch{}(处理异常)这都是我们处理异常的方式,而异常又分为受查异常(编译时异常)和非受查异常(运行时异常RuntimeException)。

编译时异常:程序不能通过编译,就是编译时异常,比如:clone时必须要通过throws来声明异常

运行时异常:指的是程序能通过编译,但是运行时出现异常。比如:NullPointerException、

ArrayIndexOutOfBoundsException、ArithmeticException。

以上的异常我们都能进行处理解决,但是错误需要程序员自己检查代码。

异常的处理

我们有两种方式来来进行处理:

一种是事前防御型:

boolean ret = false;
ret = 登陆游戏();
if (!ret) {
处理登陆游戏错误;
return;
} r
et = 开始匹配();
if (!ret) {
处理匹配错误;
return;
} r
et = 游戏确认();
if (!ret) {
处理游戏确认错误;
return;
} r
et = 选择英雄();
if (!ret) {
处理选择英雄错误;
return;
} r
et = 载入游戏画面();
if (!ret) {
处理载入游戏错误;
return;
} .
.....

事前防御型就是每一步都要检查是否出现了错误,这样的缺点就是代码显得很混乱,效率低下;

一种是事后认错型:

try {
登陆游戏();
开始匹配();
游戏确认();
选择英雄();
载入游戏画面();
...
} catch (登陆游戏异常) {
处理登陆游戏异常;
} catch (开始匹配异常) {
处理开始匹配异常;
} catch (游戏确认异常) {
处理游戏确认异常;
} catch (选择英雄异常) {
处理选择英雄异常;
} catch (载入游戏画面异常) {
处理载入游戏画面异常;
} .
....

这种做法就是将所有代码可能出现的异常全部放在try里,如果发现异常在进行捕获,这种就是先进行操作遇到问题在进行处理。

我们常常使用第二种trycatch这样使代码简洁,清晰,效率更高。

异常的抛出

如果哪段代码不符合你的预期,这段代码我们就要抛出异常,java中我们通过关键字throw来抛出异常。

语法是  throw new 异常(你要抛出的异常)

public class TestDemo {
    public static void func(int a) {
        if(a==10) {
            throw new RuntimeException("a==10不符合预期,抛出这个异常");
        }
    }
    public static void main(String[] args) {
           func(10);
    }
}

看这段代码:比如我们10这个数字不符合我们程序的预期,所以要抛出异常,我们就可以这样跑出: throw new RuntimeException("a==10不符合预期,抛出这个异常");

处理异常

我们通常有两种方式来处理异常,一种是通过throws声明异常,一种是通过try{}catch{}通过try检查代码块里是否有异常,如果有异常catch就进行捕获,如果没有异常就正常下面的代码。

throws声明异常

语法:throws 异常,异常,异常......(可声明多个异常)

public class TestDemo {
    public static void function(int[] array) {
        System.out.println(array[100]);
    }
    public static void main(String[] args) {
        int[] array = {7, 8, 9, 5, 6};
        function(array);
    }
}

大家都知道这里访问100下标是数组越界异常:

接下来通过throws来声明异常:

还是会报错。

当我们也给主函数声明异常:

答案依然会报错。

所以从这里我们得出了一个结论:通过throws只是告诉编译器,这个方法可能会发生这个异常,只是声明,但是并没有进行处理异常。我们还可以发现,如果某一个方法出现了异常,那就会看这个方法有没有处理异常,如果没有处理就去看一看上层调用者有没有处理异常。这里就是func只是声明了异常,并没有进行处理异常,然后去上层调用者有没有处理异常(也就是main方法)还是没有处理异常,最后就交给JVM来处理进行终止程序。声明的异常必须是 Exception 或者 Exception 的子类。

那怎么进行处理异常呢??  那就要通过我们接下来讲解的try{}catch来进行处理异常。

捕获异常

try{

}catch(){

}

在Java我们利用try{}catch{}来处理异常;

语法:

    try{
     //可能发生异常的代码
    }catch(异常 变量){//例如:ArrayIndexOutOfBoundsException(要捕获的异常) e(变量)
      //如果try中的代码抛出异常了,此处catch捕获时异常类型与try中抛出的异常类型一致时,
      //或者是try中抛出异常的基类时,就会被捕获到
      // 对异常就可以正常处理,处理完成后,跳出try-catch结构,继续执行后序代码
    }finally{
      //此处代码一定会执行,用于资源清理扫尾等工作
    }

我们先来讲一下try{}catch(){}

/*在方法中处理异常*/
public class TestDemo {
    public static void function(int[] array) throws ArrayIndexOutOfBoundsException {
        try{
            System.out.println(array[100]);
        }catch(ArrayIndexOutOfBoundsException e) {
            System.out.println("array[100]->数组下标越界异常catch->捕获成功");
        }
    }
    public static void main(String[] args) throws ArrayIndexOutOfBoundsException {
        int[] array = {7, 8, 9, 5, 6};
        function(array);
    }
}
/*在main方法中处理异常*/
public class TestDemo {
    public static void function(int[] array) throws ArrayIndexOutOfBoundsException {
            System.out.println(array[100]);
    }
    public static void main(String[] args) throws ArrayIndexOutOfBoundsException {
        int[] array = {7, 8, 9, 5, 6};
        try{
            function(array);
        }catch(ArrayIndexOutOfBoundsException e) {
            System.out.println("array[100]->数组下标越界异常catch->捕获成功");
        }
    }
}

我们使用try{}catch(){}就可以对异常进行处理,既可以在方法中处理异常也可以在main方法中处理异常,同时这里throws虽然没有什么用处,但是可以清晰的告诉程序员,这个方法未来可能会发生这个异常,所以还是有必要的。

try{}catch{}注意点 一:

当捕获异常成功的时候,后面的业务代码正常执行,如果没有捕获那就不会执行。

try{}catch{}注意点 二:

当try里检查到异常,catch就会捕获,计算这个异常后面还有异常也不会执行。

try{}catch{}注意点三:

throws只是声明异常,并没有处理异常,我们要通过try{}catch(){}来处理异常。

try{}catch{}注意点四:

当catch捕获的异常类型与发生异常类型不符合,就不会被捕获,就继续往外抛异常知道JVM收到后终止程序

try{}catch{}注意点五:

当发生多种异常的时候,那就要多种catch来捕获,多种异常,多次捕获。

try{}catch{}注意点六:

Exception是所有类的父类不能在前面捕获,而是应该放在最末尾进行收尾工作。

既然Exception类是所对应异常类的父类,那可不可以捕获Exception,即多次异常,一次捕获呢??

catch 进行类型匹配的时候, 不光会匹配相同类型的异常对象, 也会捕捉目标异常类型的子类对象

答案是不建议的。因为当代码进行复杂的时候,只捕获Exception类并不知道究竟是什么处理出了问题。

打印异常信息

我们还可以利用printStackTrace来打印错误信息。

finally:

finally经常与try{}catch(){}进行一起使用,finally主要是进行资源的清理,的扫尾工作,且finally一定会被执行。

我们来看这样一段代码结果会是什么??

public class TestDemo {
    public static int function(int[] array) throws ArrayIndexOutOfBoundsException {
        try {
            System.out.println(array[100]);
        }catch(ArrayIndexOutOfBoundsException e) {
            System.out.println("array[100]->数组下标越界异常catch->捕获成功");
            return -1;
        }finally{
            System.out.println("finally主要进行资源回收和清理的扫尾工作~~~");
            return 9;
        }
    }
    public static void main(String[] args) throws ArrayIndexOutOfBoundsException,ArithmeticException {
        int[] array = {7, 8, 9, 5, 6};
        System.out.println(function(array));
        System.out.println("以下是业务代码~~~~~~");
    }
}

答案并不是我们想的return-1,执行结束,而是return9,我们这里可以理解为finally的9将catch里的-1覆盖。所以finally里面的代码是一定会执行的。

异常的处理流程

我的理解:

第一步检查try里面的代码里是否有异常,如果有异常catch就进行捕获,如果没有异常接着往下执行,这里catch如果没有捕获到就看一看上层调用者有没有处理,有处理就进行处理,没有处理就交给JVM终止程序。如果catch捕获到了,下面正常的业务代码正常执行。最后无论catch是否捕获到了异常,finally里面的代码都会执行。

官方:

  • 程序先执行 try 中的代码
  • 如果 try 中的代码出现异常, 就会结束 try 中的代码, 看和 catch 中的异常类型是否匹配.
  • 如果找到匹配的异常类型, 就会执行 catch 中的代码
  • 如果没有找到匹配的异常类型, 就会将异常向上传递到上层调用者.
  • 无论是否找到匹配的异常类型, finally 中的代码都会被执行到(在该方法结束之前执行).
  • 如果上层调用者也没有处理的了异常, 就继续向上传递.
  • 一直到 main 方法也没有合适的代码处理异常, 就会交给 JVM 来进行处理, 此时程序就会异常终止。

自定义异常

在我们做很大型的项目的时候,我们就会发现,我们遇到的异常,在Java中的内置异常并没有,所以我们就需要自己定义一个异常,来维护我们实际中遇到的异常。

java 中虽然已经内置了丰富的异常类, 但是并不能完全表示实际开发中所遇到的一些异常,此时需要维护符合我们实际情况的异常结构

在Java中自己声明异常,不是说你写了个异常的名字就是一个异常,而是在你自己定义的异常需要取继承原有的内置异常。

我们通过一个登陆的代码来讲解自定义异常:

class LogIn {
    private String name ="Admin";//用户名
    private String password= "CsDn1263987..0";
    public void logInFor(String name,String password) throws UserNameErrorExecption, PasswordErrorException {
        if(!this.name.equals(name)){
            throw new UserNameErrorExecption("用户名参数异常!!!");
        }
        if(!this.password.equals(password)) {
            throw  new PasswordErrorException("用户密码参数异常!!!");
        }
        System.out.println("~~~登陆成功~~~");
    }
}
public class TestDemo{
    public static void main(String[] args) throws UserNameErrorExecption, PasswordErrorException {
        LogIn logIn = new LogIn();
        //logIn.logInFor("Admin","CsDn1263987..0");
        try{
            logIn.logInFor("Admin","CsDn126398..0");
        }catch(UserNameErrorExecption nameError) {
            nameError.printStackTrace();
            System.out.println("用户名错误!!!");
        }catch(PasswordErrorException passwordError) {
            passwordError.printStackTrace();
            System.out.println("密码错误!!!");
        }
    }
}

自定义异常:

class PasswordError extends Exception {
     public PasswordError(String message) {
           super(message);
     }
}
class UserNameError extends Exception {
    public UserNameError(String message) {
        super(message);
    }
}

这就是我们定义的两个异常。

通过继承Exception来定义两个异常。

一般我们自定义异常要继承Exception或者是RunTimeException,定义其他的也可以。

  • 自定义异常通常会继承自 Exception 或者 RuntimeException
  • 继承自 Exception 的异常默认是受查异常
  • 继承自 RuntimeException 的异常默认是非受查异常

到此这篇关于Java零基础讲解异常的文章就介绍到这了,更多相关Java异常内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java超详细梳理异常处理机制

    目录 一.异常概述与异常体系结构 1. 异常概述 引入 概念 2. 分类 2.1 Error vs Exception 2.2 编译时异常vs运行时异常 3. 常见异常 3.1 分类 3.2 代码演示 二.异常处理机制 1. 概述 2. 异常处理机制一之try-catch-finally 2.1 语法格式 2.2 使用 2.3 代码演示 3. 异常处理机制二之声明抛出异常throws 3.1 语法格式 3.2 使用 4. try-catch-finally与throws的区别 5. 手动抛出异常

  • Java 超详细讲解异常的处理

    目录 1.异常的概念和体系结构 1.1异常的概念 1.2异常的体系结构及分类 2.异常的处理 2.1防御式编程 2.2异常地抛出 2.3异常的捕获 (1)异常声明throws (2)try-catch捕获并处理 (3)finally 2.4异常的处理流程 3.自定义异常类 1.异常的概念和体系结构 1.1异常的概念 Java中,在程序执行过程中发生的不正常行为称为异常.比如之前一直遇到的: (1)算数异常 System.out.prinntln(10/0); (2)数组越界异常 int[] ar

  • Java十分钟精通异常处理机制

    目录 异常处理机制的底层原理 异常的继承关系图 异常的处理 一.try-catch-finally结构 二.多catch处理不同的异常: 三.throws声明异常/throw抛出异常: 四.自定义异常: 五.常见的异常 异常处理机制的底层原理 抛出异常,在执行一个方法时,如果发送了异常,则这个方法生成代表该异常的一个对象,停止当前执行的 路径,并把异常提交给jre. 捕获异常:jre得到该异常后,虚招相应的代码来处理该异常.jre在方法的调用栈中查找,从生成异常的 方法开始回溯,直到找到相应的异

  • Java异常处理机制深入理解

    目录 1.初识异常 2.异常的基本用法 异常处理流程 3.为什么要使用异常? 异常应只用于异常的情况 4. 异常的种类 4.1 受查异常 解决方案: 4.2非受查异常 5.如何使用异常 避免不必要的使用受查异常 6.自定义异常 1.初识异常 我们在写代码的时候都或多或少碰到了大大小小的异常,例如: public class Test { public static void main(String[] args) { int[] arr = {1,2,3}; System.out.println

  • Java8新特性Optional类处理空值判断回避空指针异常应用

    目录 一.序言 二.问题复原 (一)素材准备 (二)模拟演示 1.传统方式 2.优雅方式 三.小结 一.序言 空值异常是应用运行时常见的异常,传统方式为了编写健壮的应用,常常使用多层嵌套逻辑判断回避空指针异常.Java8新特性之Optional为此类问题提供了优雅的解决方式. 广大程序员朋友对空值异常刻骨铭心,因此Optional一经推出,广受赞誉. 二.问题复原 (一)素材准备 public class LoginUser implements UserDetails { private Lo

  • Java异常处理try catch的基本使用

    目录 1. 异常 1.1 try…catch异常处理 1.2 多catch并行处理 1.3 throw和throws 关键字的使用 1.4 finally代码块 1.5 RuntimeException异常 1.6 自定义异常 总结 1. 异常 1.1 try…catch异常处理 try catch的异常处理的格式写法 : try{ 被检测的代码 可能发生异常的代码 }catch(异常类的类名 变量名){ 异常的处理方式 : 写什么都可以 定义变量,创建对象,调用方法,循环,判断... 只要写了

  • Java 超详细讲解Spring MVC异常处理机制

    目录 异常处理机制流程图 异常处理的两种方式 简单异常处理器SimpleMappingExceptionResolver 自定义异常处理步骤 本章小结 异常处理机制流程图 系统中异常包括两类: 预期异常 通过捕获异常从而获取异常信息. 运行时异常RuntimeException 主要通过规范代码开发.测试等手段减少运行时异常的发生. 系统的Dao.Service.Controller出现都通过throws Exception向上抛出,最后SpringMVC前端控制器交由异常处理器进行异常处理,如

  • java基础详细笔记之异常处理

    目录 异常概述 常见异常的举例 空指针异常NullPointerException 数组角标越界异常ArrayIndexOutOfBoundsException 异常的抛出与捕捉 抛出异常 捕捉异常 在方法中抛出异常 使用throws关键字抛出异常 使用throw关键字抛出异常(自定义异常) 异常的使用原则 总结 异常概述 在Java中,这种在程序运行时可能出现的一些错误称为异常.异常是一个在程序执行期间发生的事件,它中断了正在执行的成宿的正常指令流. 视频笔记:  Java程序执行时遇到的异常

  • Java零基础讲解异常

    目录 什么是异常? 异常的处理 异常的抛出 处理异常 throws声明异常 捕获异常 finally: 异常的处理流程 自定义异常 什么是异常? 异常在我们写代码是特别常见,因为程序员大部分时间都在修复bug,在java中通过throwable顶层类又可以分为两个,一个是Error(错误),一个是Exception(异常). Error(错误) : Error与异常不同的是,错误并不能处理,而是程序员造成的问题,比如语法错误那就要程序员检查自己的语法,比如结果错误(StackOverflowEr

  • Java零基础教程之Windows下安装、启动Tomcat服务器方法图解(免安装版)

    相关阅读: Java零基础教程之Windows下安装 JDK的方法图解 官网下载 你是 Windows 环境,所以,打开浏览器,输入地址:http://tomcat.apache.org/download-70.cgi 选择对应的 ..-bit Windows zip下载就可以了. 安装 找到你下载的 ZIP 包,解压到你认为合适的目录,其实这是免安装版. 启动 进入 bin 目录,找到startup.bat双击,这样就算启动了 Tomcat 了,现在在浏览器输入地址+端口8080(默认)即可看

  • Java零基础教程之Windows下安装 JDK的方法图解

    官网下载 直接打开官网:http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html 我安装的是 1.7 版本,当然,你可以选择自己合适版本. 安装 下载的是.exe文件,没什么好讲的,都是直接下一步下一步.当然,你可以选择合适的安装路径,我选择了F:\Java. 接着选择jre安装路径: 环境变量 桌面上找到 计算机(此电脑)右键,点击属性--高级系统设置--环境变量,就可以开始编辑了.

  • c语言 指针零基础讲解

    1.指针是什么(可能有点难理解) 指针的是啥? 指针实际上就是地址,地址就是系统给定的编号,编号就是一个个内存单元. 在某种情况来说指针=地址=编号=内存单元. 指针就是地址,顾名思义,就是可以用来寻找目标的. 所以指针变量就是存放地址的变量. 当然我们口头上常说的指针就是指针变量~ 那指针是怎么产生的呢,也就是说内存是怎样产生的呢? 我们知道我们的计算机就是32位或64位系统组成,这32与64在物理上就是32根物理电线或64根物理电线组成.这物理电线通电时,就会产生高电频,从而产生电信号,再由

  • Java 超基础讲解String的使用

    目录 1.String概述 2.特点 3.String构造方法 4.String对象的特点 5.字符串的比较 6.实现用户登录 四.总结 1.String概述 String类在java.lang包下,所以使用的时候不需要导包. String类代表字符串,Java程序中的所有字符串文字(如:"abc")都被实现为此类的实例. 2.特点 字符串不可变,他们的值创建后不能被更改 虽然String的值是不可变的,但是它们可以被共享 字符串效果上相当于字符数组(char[ ] ),但是底层原理是

  • C语言零基础讲解指针和数组

    目录 一.指针和数组分析-上 1.数组的本质 2.指针的运算 3.指针的比较 4.小结 二.指针与数组分析-下 1.数组的访问方式 2.下标形式 VS 指针形式 3.a 和 &a 的区别 4.数组参数 5.小结 一.指针和数组分析-上 1.数组的本质 数组是一段连续的内存空间 数组的空间大小为 sizeof(array_type) * array_size 数组名可看做指向数组第一个元素的常量指针 下面看一段代码: #include <stdio.h> int main() { int

  • Java零基础入门数组

    目录 认识数组 数组的初始化 默认初始化 静态初始化 动态初始化 数组有关的问题 数组的遍历 求最值问题 查询子元素 Arrays工具类 二维数组 二维数组初始方式 二维数组的遍历 认识数组 数组的定义 数组是相同类型数据的有序集合.数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成.其中,每一个数据称作一个元素,每个元素可以通过一个索引(下标)来访问它们. 数组的四个基本特点 长度是确定的.数组一旦被创建,它的大小就是不可以改变的. 其元素的类型必须是相同类型,不允许出现混合类型

  • Java 超基础讲解String的使用

    目录 1.String概述 2.特点 3.String构造方法 4.String对象的特点 5.字符串的比较 6.实现用户登录 7.总结 1.String概述 String类在java.lang包下,所以使用的时候不需要导包. String类代表字符串,Java程序中的所有字符串文字(如:“abc”)都被实现为此类的实例. 2.特点 字符串不可变,他们的值创建后不能被更改 虽然String的值是不可变的,但是它们可以被共享 字符串效果上相当于字符数组(char[ ] ),但是底层原理是字节数组(

  • Java零基础也看得懂的单例模式与final及抽象类和接口详解

    目录 1.单例模式 1.饿汉式和懒汉式的实现 2.饿汉式 3.懒汉式 4.懒汉式和饿汉式的区别 2.final的使用 1.基本介绍 2.使用场景 3.使用注意事项和细节讨论 3.抽象类 1.基本介绍 2.使用注意事项和细节讨论 4.接口 1.基本介绍 2.注意事项和细节讨论 3.实现接口与继承的区别 4.接口与继承同时出现如何访问属性 5.接口的多态特性 1.单例模式 1.饿汉式和懒汉式的实现 步骤: 将构造器私有化 类的内部创建对象 向外暴露一个静态的公共方法 2.饿汉式 class Scho

随机推荐