Java异常 随笔,笔记分享。(学习篇)


注:网页版右上方的悬浮框有目录索引

一、异常?

程序的运行过程中所发生的不正常事件,如所需文件找不到、网络连接不能或连接中断、算术运算出错( 如被零除 )、数组下标越界、装载一个不存在的类、对 null 对象操作、类型转换异常等。异常会中断正在运行的程序。

二、Java 异常体系结构

  • 所有异常都是 Throwable 类的子类,它派生了两个类:Error 类和 Exception 类。

2.1】Error 类:

  • 表示仅靠程序本身无法恢复的严重错误
  • 如内存溢出、动态链接失败、虚拟机错误。
  • 应用程序不应该抛出这种类型的错误( 一般由虚拟机抛出 )。
  • 假如出现这种错误,应尽力使程序安全退出。

2.2】Exception 类:

  • 由 Java 应用程序抛出和处理的非严重错误
  • 如所需文件找不到、网络连接不通或连接中断、算术运算出错( 如被零除 )、数组下标越界、装载一个不存在的类、对 null 对象操作、类型转换异常等。
  • 它的各种不同的子类分别对应不同类型的异常。

2.3】Exception 可分为两大类异常

运行时异常
  • 包括 RuntimeException 及其所有子类。不要求程序必须对它们进行处理。
Checked 异常( 普通异常 )
  • 除了运行时异常外的其他从 Exception 类继承来的异常类。

  注:在进行程序设计时,应该更关注 Exception 类

三、常见的异常类

异常 说明
Exception 异常层次结构的根类
ArithmeticException 算术错误异常,如以零作为除数
ArrayIndexOutOfBoundsException 数组下标越界
NullPointerException 尝试访问 null 对象成员
ClassNotFoundException 不能加载所需的类
InputMismatchException 欲得到的数据类型与实际输入的类型不匹配
IllegalArgumentException 方法接收到非法参数
ClassCastException 对象强制类型转换出错
NumberFormatException 数字格式转换异常,如把“abc”转换成数字

四、异常处理机制

  • Java 的异常处理是通过 5 个关键字来实现的,即 try、catch、finally、throw 和 throws。

4.1】使用 try-catc 处理异常

try {
	Scanner in = new Scanner(System.in);
	System.out.print("请输入被除数:");
	int num1 = in.nextInt();
	System.out.print("请输入除数:");
	int num2 = in.nextInt();
	System.out.println(num1+"/"+ num2 +"="+ num1/ num2);
}catch (InputMismatchException e) {
	System.out.println("输入不匹配异常.....");
	e.printStackTrace();
}catch (ArithmeticException e) {
	System.out.println("算术异常........");
	e.printStackTrace();
}catch (Exception e) {
	e.printStackTrace();
}

4.1.1 三种情况

  1. 如果 try 语句块中所有语句正常执行完毕,没有发生异常,那么 catch 语句块中的所有语句都将会被忽略。
  2. 如果 try 语句块在执行过程中发生异常与 catch 语句块中声明的异常类型匹配,那么 try 语句块中剩下的代码都将被忽略,而相应的 catch 语句块将会被执行。
  3. 如果 try 语句块在执行过程中发生异常,而抛出的异常在 catch 语句块中没有被声明,那么方法立刻退出

  注:在 catch 语句中可以加入用户自定义处理信息,也可以调用异常对象的方法输出异常信息

4.1.2 异常对象的方法

void printStackTrace()
  • 输出异常的堆栈信息。堆栈信息包括程序运行到当前类的执行流程,它将输出从方法调用处到异常抛出处的方法调用实例。
String getMessage()
  • 返回异常信息描述字符串,该字符串描述了异常产生的原因,是 printStackTrace() 输出信息的一部分。

4.1.3 小结

  • 如果 try 语句块在执行过程中发生异常,try 语句块中剩下的代码都将被忽略,系统会自动生成相应的异常对象,包括异常的类型、异常出现时程序的运行状态及对该异常的详细描述。如果这个异常对象与 catch 语句块中声明的异常类型匹配,会把该异常对象赋给 catch 对象后面的异常参数,相应的 catch 语句块将会被执行。

4.2】使用 try-catch-finally 处理异常

4.2.1 大致分为两种情况

  1. 如果 try 语句块中所有语句正常执行完毕,finally 语句块也会被执行。
  2. 如果 try 语句块在执行过程中发生异常,无论这种异常能否被 catch 语句块捕获到,都将执行 finally 语句块中的代码。
特别注意
  • 即使在 catch 语句中存在 return 语句,finally 语句块中的语句也会执行。发生异常的执行顺序是,先执行 catch 语句块中 return 之前的语句,再执行 finally 语句块中的语句,最后执行 catch 语句块中的 return 语句退出。
  • finally 语句块中语句不执行的唯一情况是在异常处理代码 中执行了 System.exit(1) 退出Java 虚拟机。

  注:try-catch-finaaly 结构中 try 语句是必须存在的, catch、finally 语句块为可选,但两者至少出现其中之一

4.3】使用多重 catch 处理异常

  • 一段代码可能会引发多种类型的异常,这时,可以在一个 try 语句块后面跟多个 catch 语句块分别处理不同的异常。但排列顺序必须是从子类到父类,最后一个一般都是 Exception 类。因为按照匹配原则,如果把父类异常放到前面,后面的 catch 语句块将不会获得执行机会。
  • 运行时,系统从上到下分别对每个 catch 语句块处理的异常类型进行检测,并执行第一个与异常类型匹配的 catch 语句。执行其中的一条 catch 语句之后,其后的 catch 语句将被忽略。

4.4】使用 throws 声明抛出异常

  • 如果在一个方法体中抛出了异常,并希望调用者能够及时地捕获异常,Java 语言中通过关键字 throws 声明某个方法可能抛出的各种异常以通知调用者。throws 可以同时声明多个异常之间由逗号隔开。

抛出异常后的处理方式

  1. 过 try-catch 捕获并处理异常
  2. 通过 throws 继续声明异常。如果调用者不知道如何处理该异常,可以继续通过 throws 声明异常,让上一级调用者处理异常。main() 方法声明的异常将由 Java 虚拟机来处理。

4.5】使用 throws 抛出异常

  • 除了系统自动抛出异常外,在编程过程中,有些问题是系统无法自动发现并解决的,如年龄不在正常范围内,性别输入不合法,此时需要程序员而不是系统来自行抛出异常,并把问题交给调用者去解决。

throws 与 throw 的区别( 如下所示 )

  1. 作用不同:throw 用于程序员自行产生并抛出异常,throws 用于声明该方法内抛出了异常。
  2. 使用的位置不同:throw 位于方法体内部,可以作为单独语句使用;throws 必须跟在方法参数列表的后面,不能单独使用。
  3. 内容不同:throw 抛出一个异常对象,只能是一个;throws 后面跟异常类,可以跟多个

4.6】自定义异常

  • 当 JDK 中的异常类型不能满足程序的需要时,可以自定义异常类。使用自定义异常一般有如下几个步骤。
  1. 定义异常类,并继承 Exception 或者 RuntimeException;
  2. 编写异常类的构造方法,并继承父类的实现,常见的构造方法有如下 4 种形式。
    public Test() {
    }

    public Test(String message) {
        super(message);
    }

    public Test(String message, Throwable cause) {
        super(message, cause);
    }

    public Test(Throwable cause) {
        super(cause);
    }
  1. 实例化自定义异常对象,并在程序中使用 throw 抛出。

4.7】异常链

  • 在异常处理时有时会遇到如下情况:A 方法调用 B 方法,B 方法抛出了异常。那么 A 方法是继续招聘原有的异常还是抛出一个新异常呢?若抛出原有的异常将是很糟糕的设计方法。因为 A 方法与 B 方法进行了关联,不便于代码的修改和扩展。若抛出新的异常,虽然解决了 A 方法和 B 方法的关联问题,但是原有的异常信息却会丢失。幸运的是,JDK 1.4 推出了异常链,正好解决了这个问题。它虽然创建了新的异常,但却保留了原有异常的信息。

猜你喜欢

转载自blog.csdn.net/ice_debj/article/details/103850461