Java异常主要分为 Error 和 Exception 两种
Error: Error 类以及他的子类的实例,代表了JVM本身的错误。错误不能被程序员通过代码处理。
EXception: Exception 以及他的子类,代表程序运行时发送的各种不期望发生的事件。可以被Java异常处理机制使用,是异常处理的核心。
除了以上的分类,异常还能分为非检查异常和检查异常
非检查异常(unckecked exception):该类异常包括运行时异常(RuntimeException极其子类)和错误(Error)。编译器不会进行检查并且不要求必须处理的异常,也就说当程序中出现此类异常时,即使我们没有 try-catch 捕获它,也没有使用 throws 抛出该异常,编译也会正常通
过。因为这样的异常发生的原因很可能是代码写的有问题。
检查异常(checked exception):除了 Error 和 RuntimeException 的其它异常。这是编译器
要求必须处理的异常。这样的异常一般是由程序的运行环境导致的。因为程序可能被运行在各种未知的环境下,而程序员无法干预用户如何使用他编写的程序,所以必须处理这些异常。
下面来看下 try{}catch(){}finally{}
和 return
之间的“恩恩怨怨”,这里有些乱,面试时问的
也不是很多,实在记不住就算啦。还是先看代码猜结果。
public class Main{
public static void main(String[] args) {
int a = test1();
System.out.println(a);
int b = test2();
System.out.println(b);
int c = test3();
System.out.println(c);
int d = test4();
System.out.println(d);
int e = test5();
System.out.println(e);
}
public static int test1(){
int a = 1;
try{
a = 2;
return a;
}catch(Exception e){
System.out.println("hello,test1");
a = 3;
}finally{
a = 4;
}
return a;
}
//输出 2
public static int test2(){
int a = 1;
try{
a = 2;
return a;
}catch(Exception e){
System.out.println("hello,test2");
a = 3;
return a;
}finally{
a = 4;
}
}
//输出 2
public static int test3(){
int a = 1;
try{
a = 2/0;
return a;
}catch(Exception e){
System.out.println("hello,test3");
a = 3;
}finally{
a = 4;
}
return a;
}
//输出 hello,test3
// 4
public static int test4(){
int a = 1;
try{
a = 2/0;
return a;
}catch(Exception e){
System.out.println("hello,test4");
a = 3;
return a;
}finally{
a = 4;
}
}
//输出 hello,test4
// 3
public static int test5(){
int a = 1;
try{
a = 2/0;
return a;
}catch(Exception e){
a = 3;
return a;
}finally{
a = 4;
return a;
}
}
//输出 4
}
如果没有仔细的研究过,应该好多会猜错,下面总结下规律。
-
从前三个例子可以看出如果 try{} 中的代码没有异常, catch(){} 代码块中的代码不会执行。所以如果 try{} 和 catch(){} 都含有 return 时,无异常执行 try{} 中的 return ,存在异常执行
catch(){} 的 return 。 -
不管任何情况,就算 try{} 或 catch(){} 中含有 return , finally{} 中的代码一定会执行,那
么为什么 test1 、 test2 、 test3 中的结果不是4呢,因为虽然 finally 是在 return 后面的表达
式运算之后执行的,但此时并没有返回运算之后的值,而是把值保存起来,不管 finally 对该值做任何的改变,返回的值都不会改变,依然返回保存起来的值。也就是说方法的返回值是在 finally运算之前就确定了的。 -
如果 return 的数据是引用数据类型,而在 finally 中对该引用数据类型的属性值的改变起作用,try 中的 return 语句返回的就是在 finally 中改变后的该属性的值。这个不理解可以看看上面提到的Java的值传递的问题。
-
如果 finally{} 中含有 return ,会导致程序提前退出,不在执行 try{} 或 catch(){} 中的return 。所以 test5 返回的值是4。
最后总计一下 try{}catch(){}finally{} 的执行顺序。
- 先执行 try 中的语句,包括 return 后面的表达式;
- 有异常时,执行 catch 中的语句,包括 return 后面的表达式,无异常跳过 catch 语句;
- 然后执行 finally 中的语句,如果 finally 里面有 return 语句,执行 return 语句,程序结束;
- finally{} 中没有 return 时,无异常执行 try 中的 return ,如果有异常时则执行 catch 中的return 。前两步执行的 return 只是确定返回的值,程序并未结束, finally{} 执行之后,最后
将前两步确定的 return 的返回值返回。