错误和异常是Java中经常发生的两种现象。可是在处理层次来说,他们却并不是一样的类型。这里可以简要参考一下一下图形的说明:
从这个图里,我们可以看到异常和错误之间都是继承自Java中的Throwable接口,其中错误和运行中的异常属于unchecked异常,异常中的其他类型属于checked异常。
错误
对于错误来说,程序员通常无能为力,一旦发生,尽量想办法让程序优雅的结束。错误还分为用户的输入错误,以及设备错误,有些情况还存在着物理限制。而且一般情况下程序员对错误是不需要实例化Error的。
错误按照分类来说,还可以分为虚拟机错误和链接错误。其中虚拟机错误还分为内存溢出、堆栈越界、内部错误。而链接错误可能包含类型无法找到。
异常
针对异常来说,通常是程序本身导致的问题,因此是可以捕获的,同时也是能够处理的。
异常概念
异常是指程序执行中的非正常事件,导致程序无法再按预想的流程进行执行。Exceptions将错误信息传递给上层调用者,并报告“案发现场”的信息。异常是Java中除了return之外的第二种退出途径。在程序中如果抛出异常,那么程序就会寻找异常处理程序,如果找不到异常处理程序,那么整个系统会完全退出。
不使用异常处理,在程序中使用判断代码来进行逻辑判断的话,会使正常的逻辑代码与错误处理代码交织在一起。使用异常处理机制可以将正常的逻辑代码与错误处理代码分离。
异常的种类
异常的种类大致上可以分为两种,其中一种是运行时异常,由程序员在代码里处理不当造成。另外一种是其他异常,由外部原因造成。
运行时异常,是程序源代码中引入的故障所造成的,如果在代码中提前进行验证,这些故障就可以避免。因此这个异常的种类是可以不用编译器check的。非运行时异常,是程序员无法完全控制的外在问题所导致的,因此即使在代码中提前加以验证(文件是否存在),也无法完全避免失效发生。
checked异常与unchecked异常
checked异常,编译器可帮助检查你的程序是否已抛出或处理了可能的异常。unchecked异常不需要编译器进行检查和判断,同时编译器也不会对这个异常进行判断和捕获。可以不处理,编译没问题,但执行时出现就会导致程序失败,代表程序中的潜在bug。类似于编程语言中的
dynamic type checking
例如以下代码:
public class NullPointerExceptionExample {
public static void main(String args[]){
String str=null;
System.out.println(str.trim());
}
}
Exception in thread "main" java.lang.NullPointerException
public class ArrayIndexOutOfBoundExceptionExample {
public static void main(String args[]){
String strArray[]={"Arpit","John","Martin"};
System.out.println(strArray[4]);
}
}
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4
在编程和编译的时候,IDE与编译器均不会给出任何错误提示。Unchecked异常也可以使用throws声明或try/catch进行捕获,但大多数时候是不需要的,也不应该这么做。尽量使用unchecked exception来处理编程错误:因为unchecked exception不用使客户端代码显式的处理它们,它们自己会在出现的地方挂起程序并打印出异常信息。
关于checked异常和unchecked异常的比较可如下图所示:
Checked exception | Unchecked exception | |
---|---|---|
Basic | The compiler checks the checked exception. If we do not handle the checked exception, then the compiler objects. 必须被显式地捕获或者传递(try-catch-finally-throw),否则编译器无法通过 | The compiler does not check the Unchecked exception.Even if we do not handle the unchecked exception, the compiler doesn‘t object.异常可以不必捕获或抛出,编译器不去检查 |
Class of Exception | Except RuntimeException class, all the child classes of the class “Exception”, and the “Error” class and its child classes are CheckedException. 继承自Exception类 | RuntimeException class and its child classes, are Unchecked Exceptions.继承自 RuntimeException类 |
Handling | 从异常发生的现场获取详细的信息,利用异常返回的信息来明确操作失败的原因,并加以合理的恢复处理 | 简单打印异常信息,无法再继续处理 |
Appearance | 代码看起来复杂,正常逻辑代码和异常处理代码混在一起 | 清晰,简单 |
checked异常处理
程序员必须在方法的spec中明确写清本方法会抛出的所有checked exception,以便于调用该方法的client加以处理。函数所抛出的异常有两种,一种是你所调用的其他函数抛出了一个checked exception——从其他函数传来的异常。另一种是当前方法检测到错误并使用throws抛出了一个checked exception——你自己造出的异常。此时需要告知你的client需要处理这些异常,如果没有handler来处理被抛出的checked exception,程序就终
止执行。
简单总结如下:方法要在定义和spec中明确声明所抛出的全部checked exception。没有声明所有抛出的
checked异常,编译会出错。Unchecked异常和Error可以不用处理。