Java的异常可以分为编译异常和运行异常,其主要区别:
编译异常要求程序员必须处理(捕获或者抛出),不然没法通过编译。
而运行异常可以不处理。
这应该是纸面最明显的区别了,我认为更重要的区别是在处理机制上。
先来看看运行异常,对于运行异常,虽然不要求处理,但是运行中如果出现了运行异常程序依旧会崩。原因很简单,即使你没有对运行异常做任何处理,它会默认你是向上抛出的(谁调用的这个方法就抛给谁,抛到main方法之后就是JVM,因为JVM会调用主方法),直到抛到JVM那里如果这个异常依旧没有被捕获,JVM就会去处理,而JVM处理的方式也很简单暴力,就是把异常一输出,然后你的程序就崩了,也就不会执行下面的代码了。来看一段代码
public class M {
public static void main(String[] args) {
f1();
System.out.println("程序继续运行...");
}
static void f1() {
f2();
}
static void f2() {
int n = 2 / 0;
}
}
输出结果:
可以看到,程序就此崩了,就是因为f2方法的一个运行异常一直没有得到捕获,而是一直抛,f2抛给f1,f1抛给main,main抛给JVM,JVM直接使用了简单暴力的处理方式。而我的f1,f2,main方法都没有显示的抛出异常,而最后的异常却到了JVM那里,这就是我前面说的,没有对运行异常做任何处理,其实是默认向上抛出的。
但凡这抛到JVM之前有一个方法去捕获了这个异常,程序就不会崩掉。来看一段代码:
public class M {
public static void main(String[] args) {
f1();
System.out.println("程序继续运行...");
}
static void f1() {
try {
f2();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
static void f2() {
int n = 2 / 0;
}
}
输出结果:
/ by zero
程序继续运行...
可以看到,我在f1方法做了捕获之后,程序就可以正常运行了。
对于编译异常,编译异常是没有跟运行异常一样的默认处理机制的,要求必须自己在方法声明的时候去抛出或者在方法中捕获,不然编译没法通过。