Skip to content

Latest commit

 

History

History
184 lines (129 loc) · 8.59 KB

7_异常.md

File metadata and controls

184 lines (129 loc) · 8.59 KB

异常

异常的概念

Java 异常是一个描述在代码段中发生异常的对象,当发生异常情况时,一个代表该异常的对象被创建并且在导致该异常的方法中被抛出,而该方法可以选择自己处理异常或者传递该异常。

异常继承体系

Throwable 可以用来表示任何可以作为异常抛出的类,分为两种: ErrorException

  • Error:通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这些错误时,建议终止程序;
  • Exception:通常情况下是可以被程序处理的,捕获后可能恢复,并且在程序中应该尽可能地去处理这些异常。

Java 异常分为两种:

  • 受检异常:除了 RuntimeException 及其子类以外,其他的 Exception 类及其子类都属于这种异常
  • 非受检异常:包括 RuntimeException 及其子类和 Error。

注意:非受检查异常为编译器不要求强制处理的异常,受检异常则是编译器要求必须处置的异常。

Exception 这类异常分为运行时异常非运行时异常(编译异常)

  • 运行时异常 :包括 RuntimeException 及其子类。比如 NullPointerException、IndexOutOfBoundsException。属于非受检异常,可以进行捕捉处理,也可以不处理。
  • 非运行时异常(编译异常):RuntimeExcaption 以外的 Exception。IOException、SQLException 已经自定义的异常,必须要进行处理。

Java 异常的处理机制

Java 异常处理机制本质上就是抛出异常捕捉异常

抛出异常

i.普通问题:指在当前环境下能得到足够的信息,总能处理这个错误。

ii.异常情形:是指阻止当前方法或作用域继续执行的问题。对于异常情形,已经程序无法执行继续下去了, 因为在当前环境下无法获得必要的信息来解决问题,我们所能做的就是从当前环境中跳出,并把问题提交给上一级环境, 这就是抛出异常时所发生的事情。

iii.抛出异常后,会有几件事随之发生: ​
第一:像创建普通的java对象一样将使用new在堆上创建一个异常对象

第二:当前的执行路径(已经无法继续下去了)被终止,并且从当前环境中弹出对异常对象的引用。 ​
此时,异常处理机制接管程序,并开始寻找一个恰当的地方继续执行程序, 这个恰当的地方就是异常处理程序或者异常处理器, 它的任务是将程序从错误状态中恢复,以使程序要么换一种方式运行,要么继续运行下去。 ​
捕捉异常

在方法抛出异常之后,运行时系统将转为寻找合适的异常处理器(exception handler)。 潜在的异常处理器是异常发生时依次存留在调用栈中的方法的集合。 当异常处理器所能处理的异常类型与方法抛出的异常类型相符时,即为合适的异常处理器。 运行时系统从发生异常的方法开始,依次回查调用栈中的方法,直至找到含有合适异常处理器的方法并执行。 当运行时系统遍历调用栈而未找到合适的异常处理器,则运行时系统终止。同时,意味着Java程序的终止。

注意:

对于运行时异常、错误和受检异常,Java技术所要求的异常处理方式有所不同。

(1)由于运行时异常及其子类的不可查性,为了更合理、更容易地实现应用程序, Java规定,运行时异常将由Java运行时系统自动抛出,允许应用程序忽略运行时异常

(2)对于方法运行中可能出现的Error,当运行方法不欲捕捉时,Java允许该方法不做任何抛出声明。 因为,大多数Error异常属于永远不能被允许发生的状况,也属于合理的应用程序不该捕捉的异常。

(3)对于所有的受检异常, Java规定:一个方法必须捕捉,或者声明抛出方法之外。 也就是说,当一个方法选择不捕捉受检异常时,它必须声明将抛出异常。

Java 异常的处理原则

  • 具体明确:抛出的异常应能通过异常类名和message准确说明异常的类型和产生异常的原因;
  • 提早抛出:应尽可能早地发现并抛出异常,便于精确定位问题;
  • 延迟捕获:异常的捕获和处理应尽可能延迟,让掌握更多信息的作用域来处理异常

Java 常见异常以及错误

类型 说明
RuntimeException 子类
java.lang.ArrayIndexOutOfBoundsException 数组索引越界异常。当对数组的索引值为负数或大于等于数组大小时抛出
java.lang.ArithmeticException 算术条件异常。譬如:整数除零等
java.lang.NullPointerException 空指针异常。当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度、使用throw语句抛出null等等
java.lang.ClassNotFoundException 找不到类异常。当应用试图根据字符串形式的类名构造类,而在遍历CLASSPAH之后找不到对应名称的class文件时,抛出该异常
java.lang.SecurityException 安全性异常
java.lang.IllegalArgumentException 非法参数异常
IOException
IOException 操作输入流和输出流时可能出现的异常
EOFException 文件已结束异常
FileNotFoundException 文件未找到异常
其他
ClassCastException 类型转换异常类
ArrayStoreException 数组中包含不兼容的值抛出的异常
SQLException 操作数据库异常类
NoSuchFieldException 字段未找到异常
NumberFormatException 字符串转换为数字抛出的异常
StringIndexOutOfBoundsException 字符串索引超出范围抛出的异常
IllegalAccessException 不允许访问某类异常
Error
NoClassDefFoundError 找不到class定义的错误
StackOverflowError 深递归导致栈被耗尽而抛出的错误
OutOfMemoryError 内存溢出错误

Java异常常见面试题

try-catch-finally语句块的执行


(1)try 块:用于捕获异常。其后可接零个或多个catch块,如果没有catch块,则必须跟一个finally块。

(2)catch 块:用于处理try捕获到的异常。

(3)finally 块:无论是否捕获或处理异常,finally块里的语句都会被执行。 当在try块或catch块中遇到return语句时,finally语句块将在方法返回之前被执行。

在以下4种特殊情况下,finally块不会被执行:

1)在finally语句块中发生了异常。 ​
2)在前面的代码中用了System.exit()退出程序。

3)程序所在的线程死亡。

4)关闭CPU。

try catch代码块的性能如何?

  1. 会影响JVM的重排序优化;
  2. 异常对象实例需要保存栈快照等信息,开销比较大。

final和finally和finalize的区别?

(1)final:最终的意思,可以修饰类,修饰成员变量,修饰成员方法

修饰类:类不能被继承 ​
修饰变量:变量是常量 ​
修饰方法:方法不能被重写(Override)

(2)finally:是异常处理的关键字,用于释放资源。一般来说,代码必须执行(特殊情况:在执行到finally JVM就退出了)

(3)finalize:是Object的一个方法,用于垃圾回收。

  • 看程序写结果
public class TestException {
    public static void main(String[] args) {
        System.out.println(getInt());
    }

    public static int getInt(){
        int a=10;
        try{
            System.out.println(a/0);
        }catch (ArithmeticException e){
            a=30;
            return a; 
        }finally {
            a=40;
        }
        System.out.println("a="+a);
        return a;
    }
}

结果为:

30