1. checked和unchecked异常基本概念
具体见下边的文档。
https://www.javatpoint.com/exception-handling-in-java
异常分为两大类,Exception和Error(这里将Error也说为异常,可以有些不准确哦)。
而Exeption又分为IOException,SQLException, ClassNotFoundException, RuntimeException等。其中RuntimeException又可以包含很多种类异常。具体结构层次见下图。
从程序员需不需要在代码中处理的角度,这些异常总体可以分为两大类: checked和unchecked。
checked异常,主要指继承自Exception的那些除了RuntimeException的异常。checked异常需要程序员自己做处理,比如在方法A中调用了会抛出checked异常的方法B,那么在编译阶段,编译器会强制要求你在方法A中用try...catch...捕获处理, 或者通过throws让所在的方法抛出。
unchecked异常,主要是指继承自RuntimeException,以及那些继承自Error的异常,编译器是不会强制要求程序员自己处理的,会由JVM虚拟机直接处理。
比如下边的测试代码,只有在调用testCheckedExeption()时,才需要在main()方法中处理异常,其他两种情况都不需要。
注:IllegalArgumentException也属于RuntimeException哦
另外,异常并不是一定由程序通过throw关键字抛出,JVM在运行时也会抛出异常的。
public static void main(String[] args) /*throws IOException*/ {
// testCheckedExeption();
// testUnCheckedExeption();
testError();
}
public static void testCheckedExeption() throws IOException {
throw new IOException();
}
public static void testUnCheckedExeption(){
throw new IllegalArgumentException();
}
public static void testError(){
throw new OutOfMemoryError();
}
2. unchecked异常能像checked异常一样被捕获么?
答案是可以的,如果您愿意,unchecked异常也可以像checked异常一样来处理。比如下边的代码,一样会打印IllegalArgumentException和OutOfMemoryError的stack trace.
public static void main(String[] args) /*throws IOException*/ {
try{
testUnCheckedExeption();
testError();
}catch(Exception e){
e.printStackStrace();
}
}
public static void testCheckedExeption() throws IOException {
throw new IOException();
}
public static void testUnCheckedExeption(){
throw new IllegalArgumentException();
}
public static void testError(){
throw new OutOfMemoryError();
}
3. 既然checked和unchecked异常都能被捕获(只要程序员想),那为什么异常要分为checked和unchecked呢?
这个主要是java的设计角度考虑。unchecked异常,主要是指那些客户端调用程序一般无法处理的异常(方法A调用会抛出异常的方法B,A就是客户端),比如被0除的ArithmeticExeption, 空指针异常,数组过界异常等。当您写的类的方法抛出这种unchecked异常,就表示您不期望客户端调用程序来合理的处理它,或者说您不指望客户端程序能合理的从这种异常中恢复,而是直接挂掉(抛给jvm处理,客户端调用线程会退出)。这是设计unchecked 异常一个原因。另外一个原因是程序中会抛出这种unchecked异常的地方太多了,如果每个地方都需要try catch,那整个的程序可读性也就大大下降了。具体可以参考下边的官方文档:
https://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html
为了客户端调用方便,可能很多人都会在自己的程序中抛出unchecked异常,这样客户端调用时就省事了,不用处理该异常。但这并不是一个好的做法。
正如这个文档末尾所说的,在您设计您的类的方法该抛出什么异常的时候,如果您期待客户端调用程序能够从您的类的方法中抛出的异常中正常合理的恢复,那么您的类的方法就抛checked的异常,如果是您期待客户端不能够也不应该做任何事情尝试从该异常中恢复,那么您的方法就抛出unchecked异常。