Java中关于try...catch的return规则
本部分针对有
return要求的异常捕获和处理,具体的,try...catch语句存在于一个方法体中。方法体中的
try...catch的return总共有四种可能的地方:
try,catch,finally,方法体末尾(try…catch外)。
共存规则
finally中的return和方法return不能同时存在。(显而易见的第一法则!)try中的return和catch中的return都有的时候,finally中的return可有可无,但是不能有方法return(编译器提示:方法return不可到达)try和catch中只有一个有return时,finally中的return和方法return必须有且只能有一个。(否则:缺少return)
共存问题还是很好理的。只要保证每种情况都必须有return就行。
ps.IDEA比较牛逼会在一定程度上分析逻辑……比如如果
try里头第一句就是throw的话,try里的return也是会报错的。
int i=1;
try {
throw new Exception();
return i;
}//这样会报错。
--- --- --- --- ---
int i=1;
try {
if(i==1) throw new Exception();
return i;
}//但是这样不会。
执行顺序
规则
try里头抛出异常被捕获后,try中之后的语句是不会被执行的,而是直接跳转到相应的catch。- 无论如何,
finally中的语句都会在方法返回之前被执行。 - 当
finally中有return时,它会覆盖try和catch中的return。 - 当方法体末尾有
return,try或catch中(这三个都有会报错)有一个return时,执行到后者的return后,执行完finally中的内容就会直接返回,不会执行finally之后、方法体结束前的语句。 return返回的是一个引用,(可以理解为一个物理地址?)所以当只有try和catch中有return时,如果返回的是不可变类型,那么finally中对对象的”修改“实际上是创建了一个新对象,返回的自然是原来的值;如果返回的是可变类型,finally中的修改就会对返回值生效。
实例
-
懒得打了,跳过。
int i=1;
try{
throw new Exception();
}catch(Exception e){
return i;//返回值为1
}finally{
i++;
System.out.println(i);//输出为2
}
finally块的递增操作不会影响catch块中的返回值,因为catch块已经执行完毕并返回了值,finally块中的代码只是在方法返回之前执行的。
-
public static int get0() { int i=1; try { throw new Exception(); } catch (Exception e) { System.out.println("error"); return i; } finally { i++; System.out.println("i in finally block:" + i); return i;//最终返回2 } }finally中的return覆盖了之前的return。 -
public static int get3(){ int i=1; try{ i++; System.out.println("Do try"); return i; }catch(Exception e) { i++; System.out.println("Do catch"); }finally { i++; System.out.println("Do finally"); } System.out.println("END"); return i; }main中执行System.out.println(get3()),输出结果为:Do try Do finally 2可以看出,方法体最后两行语句时没有被执行的;只有进入
catch时才会执行。 -
public static String get1() { String i = "ok"; try { throw new Exception(); } catch (Exception e) { System.out.println("error"); return i;//最终返回"ok" } finally { i += " finally"; System.out.println("i in finally: " + i);//输出i in finally: ok finally } } public static StringBuilder get2() { StringBuilder i = new StringBuilder("ok"); try { throw new Exception(); } catch (Exception e) { System.out.println("error"); return i;//返回ok finally } finally { i.append(" finally"); System.out.println("i in finally: " + i);//输出i in finally: ok finally } }其中,
String(包括get0()中的int)是不可变类型,而StringBuilder是可变类型,因此导致了返回结果的不同。
当然,自己写代码时有事没事不要往finally里面加return,会导致调试复杂化。
后记
原本以为方法体末尾的return和finally中的效果是一样的,后来发现并非如此……感谢室友的指正(鞠躬)。
一些细节的地方没有测试,另外IDEA好像有些高级的逻辑判断机制,判断有return无法到达时都会报错。但也不是那么高级加个简单的if判断就不会报错了之后会拿其他编译器试试。
感谢看到这里的你。

浙公网安备 33010602011771号