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判断就不会报错了之后会拿其他编译器试试。
感谢看到这里的你。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 上周热点回顾(2.17-2.23)