1.throw和throws
- 抛出异常有三种形式,一是throw,一个throws,还有一种系统自动抛异常。
- 系统自动抛出的异常
所有系统定义的编译和运行异常都可以由系统自动抛出,称为标准异常,并且 Java 强烈地要求应用程序进行完整的异常处理,给用户友好的提示,或者修正后使程序继续执行。
- throw
throw是语句抛出的异常,一般在代码块内部,当程序出现某种逻辑错误时由程序员主动抛出某种特定类型的异常
throw(异常对象);
throw e;
- throws
throws是方法可能抛出异常的声明(用在声明方法时,表示该方法可能要抛出异常,然后交给上层调用它的方法程序处理)
public void A (int a) throws Exception{...}
- throw和throws比较
throws出现在方法函数头;而throw出现在函数体。
throws表示出现异常的一种可能性,并不一定会发生这些异常;throw则是抛出了异常,执行throw则一定抛出了某种异常对象。
两者都是消极处理异常的方式(这里的消极并不是说这种方式不好),只是抛出或者可能抛出异常,但是不会由函数去处理异常,真正的处理异常由函数的上层调用处理。
- 编程习惯
在写程序时,对可能会出现异常的部分通常要用try{...}catch{...}去捕捉它并对它进行处理;
用try{...}catch{...}捕捉了异常之后一定要对在catch{...}中对其进行处理,那怕是最简单的一句输出语句,或栈输入e.printStackTrace();
如果是捕捉IO输入输出流中的异常,一定要在try{...}catch{...}后加finally{...}把输入输出流关闭;
如果在函数体内用throw抛出了某种异常,最好要在函数名中加throws抛异常声明,然后交给调用它的上层函数进行处理。
2.final、finally和finalize
- final
final用来修饰属性,方法和类
修饰属性时,表示属性不可变,它只能指向初始时指向的的对象,本质上,final修饰的是引用,对象不可改变,但是对象的内容可以改变;
修饰方法时,表示方法不可以被子类重写,但是依然可以被子类引用;
修饰类时,表示类不能被继承,里面的方法不可以被重写
- finally
finally作为异常处理的一部分,只能用于try/catch语句中,并且附带一个语句块,没有意外情况,try/catch语句执行,finally语句一定会执行
- finalize
finalize是Object类的一个方法,当gc执行时,会调用被回收对象的finalize()方法,可以覆盖此方法实现对其他资源的回收。需要注意的是,一旦垃圾回收器准备好释放对象占用的空间,将首先调用其finalize()方法,并且在下一次垃圾回收发生时,才会真正回收对象占用的内存
3.try-catch-finally 中哪个部分可以省略
- catch-finally可以省略其中一个,但catch和finally语句不能同时省略
try-catch
try-finally
try-catch-finally
4.当try、catch中有return时,finally中的代码会执行吗
- 会,不管有没有异常,finally中的代码都会执行
1.当try、catch中有return时,finally中的代码依然会继续执行
2.finally是在return后面的表达式运算之后执行的,此时并没有返回运算之后的值,而是把值保存起来,不管finally对该值做任何的改变,返回的值都不会改变,依然返回保存起来的值。也就是说方法的返回值是在finally运算之前就确定了的。
3.如果return的数据是引用数据类型,而在finally中对该引用数据类型的属性值的改变起作用,try中的return语句返回的就是在finally中改变后的该属性的值。
4.finally代码中最好不要包含return,程序会提前退出,也就是说返回的值不是try或catch中的值
1.先执行try中的语句,包括return后面的表达式,
2.有异常时,先执行catch中的语句,包括return后面的表达式,
3.然后执行finally中的语句,如果finally里面有return语句,会提前退出
,最后执行try中的return,有异常时执行catch中的return。
4.在执行try、catch中的return之前一定会执行finally中的代码(如果finally存在),如果finally中有return语句,就会直接执行finally中的return方法,所以finally中的return语句一定会被执行的。编译器把finally中的return语句标识为一个warning.
5.常见的异常类
- RuntimeException子类
序号 | 异常名称 | 异常描述 |
---|---|---|
1 | java.lang.ArrayIndexOutOfBoundsException | 数组索引越界异常。当对数组的索引值为负数或大于等于数组大小时抛出 |
2 | java.lang.ArithmeticException | 算术条件异常譬如:整数除零等。 |
3 | java.lang.SecurityException | 安全性异常 |
4 | java.lang.IllegalArgumentException | 非法参数异常 |
5 | java.lang.ArrayStoreException | 数组中包含不兼容的值抛出的异常 |
6 | java.lang.NegativeArraySizeException | 数组长度为负异常 |
7 | java.lang.NullPointerException | 空指针异常。当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度、使用throw语句抛出null等等。 |
- IOException
序号 | 异常名称 | 异常描述 |
---|---|---|
1 | IOException | 操作输入流和输出流时可能出现的异常 |
2 | EOFException | 文件已结束异常 |
3 | FileNotFoundException | 文件未找到异常 |
- 其他
序号 | 异常名称 | 异常描述 |
---|---|---|
1 | ClassCastException | 类型转换异常类 |
2 | ArrayStoreException | 数组中包含不兼容的值抛出的异常 |
3 | SQLException | 操作数据库异常类 |
4 | NoSuchFieldException | 字段未找到异常 |
5 | NoSuchMethodException | 方法未找到抛出的异常 |
6 | NumberFormatException | 字符串转换为数字抛出的异常 |
7 | StringIndexOutOfBoundsException | 字符串索引超出范围抛出的异常 |
8 | IllegalAccessException | 不允许访问某类异常 |
9 | InstantiationException | 当应用程序试图使用Class类中的newInstance()方法创建一个类的实例,而指定的类对象无法被实例化时,抛出该异常 |
10 | java.lang.ClassNotFoundException | 找不到类异常。当应用试图根据字符串形式的类名构造类,而在遍历CLASSPAH之后找不到对应名称的class文件时,抛出该异常。 |
6.异常
程序开发和运行过程中会出现
编译错误
和运行错误
。编译错误容易被发现并排除,而运行错误(逻辑错误和异常)很难预料。因此为了程序的稳定性和可靠性,就需要对程序异常处理和保护。
异常( Exception ):正常程序流程所不能处理或者没有处理的异常情况或异常事件
。
- Throwable
有两个重要的子类:Exception(异常)和 Error(错误),二者都是 Java 异常处理的重要子类,各自都包含大量子类。异常和错误的区别是:异常能被程序本身可以处理,错误是无法处理。
Error(错误):是程序无法处理的错误,表示运行应用程序中较严重问题。
Exception(异常):是程序本身可以处理的异常。分两大类:运行时异常和非运行时异常(编译异常)。
非运行时异常 (编译异常):是RuntimeException以外
的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常
运行时异常:都是RuntimeException类及其子类异常
,如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。
image.png
Java的异常(Throwable)分为可查的异常(checked exceptions)
和不可查的异常(unchecked exceptions)
。
可查异常(编译器要求必须处置的异常):正确的程序在运行中,很容易出现的、情理可容的异常状况。除了Exception中的RuntimeException及RuntimeException的子类以外,其他的Exception类及其子类(例如:IOException和ClassNotFoundException)都属于可查异常。这种异常的特点是Java编译器会检查它,也就是说,当程序中可能出现这类异常,要么用try-catch语句捕获它,要么用throws子句声明抛出它,否则编译不会通过。
不可查异常(编译器不要求强制处置的异常):包括运行时异常(RuntimeException与其子类)和错误(Error)。RuntimeException表示编译器不会检查程序是否对RuntimeException作了处理,在程序中不必捕获RuntimException类型的异常,也不必在方法体声明抛出RuntimeException类。RuntimeException发生的时候,表示程序中出现了编程错误,所以应该找出错误修改程序,而不是去捕获RuntimeException。
异常处理机制
在 Java 应用程序中,异常处理机制为:抛出异常,捕捉异常。
抛出异常:throw和throws
捕捉异常:try/catch/finally语句