在 Java 实际开发中,往往会遇到很多异常,对异常进行处理便是我们必备的一个技能,比较常见的就是 try...catch..finally 结构,今天我们就来讲讲这个结构的运行逻辑。
正常情况下:
public class Demo {
public static void main(String[] args){
System.out.println(getValue());
}
public static int getValue(){
int value = 1;
try{
System.out.println("-----try 被执行了----");
value = 2;
System.out.println("-----try 要执行结束了----");
}catch (Exception e){
System.out.println("-----catch 被执行了----");
value = -1;
}
finally {
System.out.println("-----finally 被执行了----");
value = 0;
}
return value;
}
}
执行结果:
-----try 被执行了----
-----try 要执行结束了----
-----finally 被执行了----
0
因为没有发生异常,所以没有执行 catch 中的语句,先执行了 try 再执行了 finally。
异常情况:
public static int getValue(){
int value = 1;
try{
System.out.println("-----try 被执行了----");
value = 1 / 0;
System.out.println("-----try 要执行结束了----");
}catch (Exception e){
System.out.println("-----catch 被执行了----");
value = -1;
}
finally {
System.out.println("-----finally 被执行了----");
value = 0;
}
return value;
}
执行结果:
-----try 被执行了----
-----catch 被执行了----
-----finally 被执行了----
0
可以看出,因为出现异常,代码按着 try - catch - finally 的循序执行了,而且 try 中一出现异常就不运行后面的代码直接执行 catch 语句中的代码。
从上面两个例子可以看出,finally 语句是一定会被执行的,那么要是我将 return 语句卸载 try 语句 和 catch 语句中呢?
正常情况:
public static int getValue(){
int value = 1;
try{
System.out.println("-----try 被执行了----");
value = 2;
System.out.println("-----try 要执行结束了----");
return value;
}catch (Exception e){
System.out.println("-----catch 被执行了----");
value = -1;
return value;
}
finally {
System.out.println("-----finally 被执行了----");
value = 0;
}
}
执行结果:
-----try 被执行了----
-----try 要执行结束了----
-----finally 被执行了----
2
这里可以看出 finally 确实被执行了,但是 value 的值却返回的是 2,按照执行循序来说,不应该返回 0 吗?那我们再来看看异常情况呢?
异常情况:
public static int getValue(){
int value = 1;
try{
System.out.println("-----try 被执行了----");
value = 1 / 0;
System.out.println("-----try 要执行结束了----");
return value;
}catch (Exception e){
System.out.println("-----catch 被执行了----");
value = -1;
return value;
}
finally {
System.out.println("-----finally 被执行了----");
value = 0;
}
}
执行结果:
-----try 被执行了----
-----catch 被执行了----
-----finally 被执行了----
-1
是不是很奇怪,执行循序和之前执行循序一样,但是值却返回的 catch 语句中的值,那么我们可以去看看它的字节码是如何运行的,但是我没调出字节码,具体可以参考一下这个:
java中关于try、catch、finally中的细节分析 - 猫叔玩流量 - 博客园 (cnblogs.com)https://www.cnblogs.com/aigongsi/archive/2012/04/19/2457735.html我就直接说原因了,因为 return 返回的是一个引用类型,再返回这个类型之前,系统会新建一个引用类型将原来引用类型的值付给它,而执行 finally 语句所赋值的是原来的引用类型,所以最后返回的值是 try 或 catch 语句中的值。
还有种情况,那就是 return 语句在 finally 语句中呢?
public static int getValue(){
int value = 1;
try{
System.out.println("-----try 被执行了----");
value = 1 / 0;
System.out.println("-----try 要执行结束了----");
return value;
}catch (Exception e){
System.out.println("-----catch 被执行了----");
value = -1;
return value;
}
finally {
System.out.println("-----finally 被执行了----");
value = 0;
return value;
}
}
结果:
-----try 被执行了----
-----catch 被执行了----
-----finally 被执行了----
0
可以看到虽然 try 语句和 catch 语句都有 return 语句,但是最终返回的依然是 finally 语句中修改的值。
综上所述,我们将try...catch...finally结构的运行逻辑分为以下三点:
- 先执行 try 语句,有异常执行 catch 语句并且不运行 try 语句报异常位置为后面代码,finally 语句一定被执行。
- try 或 catch 语句中存在 return 语句,在执行 return 语句之前一定会运行 finally 语句中的代码,但是 finally 语句对返回的值做的修改不会影响原来的返回值。
- finally 语句中的 return 语句一定会被返回。
想要了解更多关于异常的知识,推荐去看看这个大佬的:
Java中的try-catch-finally异常处理 - StarHai - 博客园 (cnblogs.com)https://www.cnblogs.com/csushl/p/11973468.html不积跬步无以至千里,不积小流无以成江海,多动手实践一下才能真正理解。