本渣今天帮师兄做笔试,读Java程序 发现答案跟我想的完全不一样,最后一查才发现自己想的完全是错的
,赶紧记录一下,希望能帮到需要的人。
在实际开发中,根据 try catch 语句的执行过程,try 语句块和 catch 语句块有可能不被完全执行,而有些处理代码则要求必须执行,例如文件的关闭、释放资源等,此时就可以将这些代码放在 finally 语句块中。
finally 语句可以与前面介绍的 try catch 语句块匹配使用,语法格式如下:
try{
逻辑代码块
}catch(ExceptionType e){
异常处理代码块
}finally{
清理代码块
文件关闭
释放资源
}
图一 try catch finally
语句执行流程图
try catch finally
语句块的执行情况可以细分为以下 5 种情况:
- 如果 try 代码块中没有拋出异常,则执行完 try 代码块之后直接执行 finally 代码块,然后执行 try catch finally 语句块之后的语句。
- 如果 try 代码块中拋出异常,并被 catch 子句捕捉,那么在拋出异常的地方终止 try 代码块的执行,转而执行相匹配的 catch 代码块,之后执行 finally 代码块。如果 finally 代码块中没有拋出异常,则继续执行 try catch finally 语句块之后的语句;如果 finally 代码块中拋出异常,则把该异常传递给该方法的调用者。
- 如果 try 代码块中拋出的异常没有被任何 catch 子句捕捉到,那么将直接执行 finally 代码块中的语句,并把该异常传递给该方法的调用者。
- 在前面的代码中用 System.exit() 退出运行。如果代码在 try 内部执行一条 System.exit() 语句,则应用程序将终止而不会执行 finally。
- 如果在执行 finally 块之前,程序所在的线程死亡,finally 块将不被执行。
实例1:
我知道 return a++;
是先 return 再+1的,但是如果用try/finally
语句捕获时,突然发现有三种有趣的情况:
1. return a++;
2. return ++a;
3. return a+1;
分别在finally语句会有不同的输出。
public class test {
public static void main(String[] args) {
System.out.println("s:"+test(1));
}
static int test(int a){
try {
//依次修改此处
return a++;
//return ++a;
//return a+1;
}finally {
System.out.println("f:"+a);
}
}
}
- return a++;
f:2
s:1
- return ++a;
f:2
s:2
- return a+1;
f:1
s:2
我们知道finally语句是在方法结束前运行的,
原因:程序中try内部没有异常的情况下,若有finally,且finally中没有return。若在try中遇到return,则先跳去执行finally中的代码,在回来执行try中return。
其实上述代码反编译字节码之后会发现:
原来其实return后面的表达式,编译器会创建临时变量,操作完成再返回
import java.io.PrintStream;
public class Test
{
public Test()
{
}
public static void main(String args[])
{
System.out.println((new StringBuilder()).append("s:").append(test(1)).toString());
}
static int test(int a)
{
int i = a++;//主要改此处
System.out.println((new StringBuilder()).append("f:").append(a).toString());
return i;
Exception exception;
exception;
System.out.println((new StringBuilder()).append("f:").append(a).toString());
throw exception;
}
}
实例2:
public class TryTest {
public static void main(String[] args) {
String result = get();
System.out.println(result);
}
public static String get(){
int value = 0;
try {
System.out.println("try……");
//等式1/0 :分母为0 的明显错误 ——制造错误(用于抛异常)
int result = 1 / value;
return "111";
} catch (Exception e) {
System.out.println("catch……");
return "444";
} finally {
System.out.println("finally……");
return "333";
}
// return "222";
}
结果:
经过测试:
- 在通过编译器的检查后,如果finally中有return,则以finally中的return为准,其他的都将失效,return之前的代码都有效。
- 第37行的return “222” 于catch、finally中的任何一个return互斥。也就是说,在catch、finally中其中一个地方存在return,编译器就能检查,已符合方法的返回要求。
- catch和finally中,可同时存在return,编译能通过。但程序以finally中的return “333”为准,不会理睬catch中的return “444”,catch中return之前的代码仍然生效。
实例3:以下程序不会执行 try……Catch……finally之外的return,即打印的是“111”,而不打印“222”。
public static void main(String[] args) {
// 调用 测试方法
String result = get();
// 打印 测试方法返回的结果
System.out.println(result);
}
public static String get(){
try {
System.out.println("try……");
return "111";
} catch (Exception e) {
System.out.println("catch……");
} finally {
System.out.println("finally……");
}
return "222";
}
结果:
参考文献1:try、catch、finally中return的执行顺序
参考文献2:finally语句与return a++