异常分类
Error
类层次结构描述了 Java 运行时系统的内部错误和资源耗尽错误。程序不应该抛出这种类型的对象
平时在设计 Java 程序时,需要关注Exception层次结构。
Java 语言规范将派生于Error类或RuntimeException类的所有异常称为不受检查性( unchecked)异常,所有其他的异常称为检查性 (checked)异常。编译器将核查是否为所有的检查性异常提供了异常处理器。
除了
RuntimeException
及其子类以外,其他的Exception
类及其子类都属于检查异常,当程序中可能出现这类异常,要么使用try-catch
语句进行捕获,要么用throws
子句抛出,否则编译无法通过。
自定义异常类
用户自定义异常类,只需继承Exception
类即可。
在程序中使用自定义异常类,大体可分为以下几个步骤:
- 创建自定义异常类。
- 在方法中通过
throw
关键字抛出异常对象。 - 如果在当前抛出异常的方法中处理异常,可以使用
try-catch
语句捕获并处理;否则在方法的声明处通过throws
关键字指明要抛出给方法调用者的异常,继续进行下一步操作。 - 在出现异常方法的调用者中捕获并处理异常。
try-catch 语句
try{
//code that might generate exceptions
}catch(Exception e){
//the code of handling exception1
}catch(Exception e){
//the code of handling exception2
}
上述try-catch
所描述的即是监控区域。java
方法在运行过程中发生了异常,则创建异常对象。将异常抛出监控区域之外,由java
运行时系统负责寻找匹配的catch
子句来捕获异常。若有一个catch
语句匹配到了,则执行该catch
块中的异常处理代码,就不再尝试匹配别的catch
块了。
匹配的原则是:如果抛出的异常对象属于
catch
子句的异常类,或者属于该异常类的子类,则认为生成的异常对象与catch
块捕获的异常类型相匹配。
finally
当代码抛出一个异常时,就会终止方法中剩余代码的处理,并退出这个方法的执行
- 不管是否有异常被捕获.
finally
子句中的代码都被执行 try
语句可以只有finally
子句,而没有catch
子句
异常声明 throws
如果一个方法会导致一个异常但不处理它,它必须声明该异常以使方法的调用者可以保护它们自己而不发生异常。
如果某个方法不想处理所导致的异常,因而它必须声明
throws
子句来声明可能引发的异常;然后,在方法调用处必须定义try/catch
语句来捕获该异常。
异常声明遇到继承时
- 当子类在重写父类的一个函数时,不能声明抛出比父类的版本更多的异常
- 在子类的构造函数中必须声明父类可能抛出的全部异常
java 异常处理
Java 的异常处理是通过 5 个关键词来实现的:try
、catch
、throw
、throws
和finally
。一般情况下是用try
来执行一段程序,如果系统会抛出(throw
)一个异常对象,可以通过它的类型来捕获(catch
)它,或通过总是执行代码块(finally
)来处理;try
用来指定一块预防所有异常的程序;catch
子句紧跟在try
块后面,用来指定你想要捕获的异常的类型;throw
语句用来明确地抛出一个异常;throws
用来声明一个方法可能抛出的各种异常(当然声明异常时允许无病呻吟);finally
为确保一段代码不管发生什么异常状况都要被执行;try
语句可以嵌套,每当遇到一个try
语句,异常的结构就会被放入异常栈中,直到所有的try
语句都完成。如果下一级的try
语句没有对某种异常进行处理,异常栈就会执行出栈操作,直到遇到有处理这种异常的try
语句或者最终将异常抛给JVM
。
finally 包含 return 时
注意
假设利用return
语句从try
语句块中退出。在方法返回前,finally
子句的内容将被执行。如果finally
子句中也有一个return
语句,这个返回值将会覆盖原始的返回值。
public class Demo {
public static int f(int n) {
try {
int r = n * n;
return r;
} finally {
if (n == 2) return 0;
}
}
public static void main(String[] args) {
System.out.println(f(2));
}
}
上述代码的输出为0
,原来的r=4
被覆盖了
问题扩展:
1、try{} 里有一个 return 语句,那么紧跟在这个 try 后的 finally{} 里的 code 会不会被执行,什么时候被执行,在 return 前还是后?
答案:会执行,在方法返回调用者前执行。
带资源的try
语句
带资源的try
语句(try-with-resources
)的最简形式为:
try (Resource res = . . .) {
work with res
}
public class Demo {
public static void main(String[] args) {
try(Scanner sc = new Scanner(new FileInputStream("src\\main\\java\\AnonymousInnerClassTest\\1.txt"),
"UTF-8")) {
while (sc.hasNext()) {
System.out.println(sc.next());
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}
}