忽然发现自己try catch finally中有返回值的情况下记得有点混乱,开篇帖子仔细研究研究。
不愿意看示例的直接看最后,有总结,看完基本就懂了。
第一种情况:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
首先程序执行try语句块,把变量t赋值为try,由于没有发现异常,接下来执行finally语句块,把变量t赋值为finally,然后return t,则t的值是finally,最后t的值就是finally,程序结果应该显示finally,但是实际结果为try。
在try语句的return块中,return 返回的引用变量(t 是引用类型)并不是try语句外定义的引用变量t,而是系统重新定义了一个局部引用t’,这个引用指向了引用t对应的值,也就是try ,即使在finally语句中把引用t指向了值finally,因为return的返回引用已经不是t ,所以引用t的对应的值和try语句中的返回值无关了。
第二种:
1 public class TryCatchFinally { 2 3 @SuppressWarnings("finally") 4 public static final String test() { 5 String t = ""; 6 7 try { 8 t = "try"; 9 return t; 10 } catch (Exception e) { 11 // result = "catch"; 12 t = "catch"; 13 return t; 14 } finally { 15 t = "finally"; 16 return t; 17 } 18 } 19 20 public static void main(String[] args) { 21 System.out.print(TryCatchFinally.test()); 22 } 23 24 }
这里稍微修改了 第一段代码,只是在finally语句块里面加入了 一个 return t 的表达式。
按照第一段代码的解释,先进行try{}语句,然后在return之前把当前的t的值try保存到一个变量t',然后执行finally语句块,修改了变量t的值,在返回变量t。可能jvm认为一个方法里面有两个return语句并没有太大的意义,所以try中的return语句给忽略了,直接起作用的是finally中的return语句,所以这次返回的是finally。
接下来在看看复杂一点的例子:第三种
public class TryCatchFinally { @SuppressWarnings("finally") public static final String test() { String t = ""; try { t = "try"; Integer.parseInt(null); return t; } catch (Exception e) { t = "catch"; return t; } finally { t = "finally"; // System.out.println(t); // return t; } } public static void main(String[] args) { System.out.print(TryCatchFinally.test()); } }
这里面try语句里面会抛出 java.lang.NumberFormatException,所以程序会先执行catch语句中的逻辑,t赋值为catch,在执行return之前,会把返回值保存到一个临时变量里面t ',执行finally的逻辑,t赋值为finally,但是返回值和t',所以变量t的值和返回值已经没有关系了,返回的是catch
第四种:
public class TryCatchFinally { @SuppressWarnings("finally") public static final String test() { String t = ""; try { t = "try"; Integer.parseInt(null); return t; } catch (Exception e) { t = "catch"; return t; } finally { t = "finally"; return t; } } public static void main(String[] args) { System.out.print(TryCatchFinally.test()); } }
这个和 第二种 有点类似,由于try语句里面抛出异常,程序转入catch语句块,catch语句在执行return语句之前执行finally,而finally语句有return,则直接执行finally的语句值,返回finally
5:
public class TryCatchFinally { @SuppressWarnings("finally") public static final String test() { String t = ""; try { t = "try"; Integer.parseInt(null); return t; } catch (Exception e) { t = "catch"; Integer.parseInt(null); return t; } finally { t = "finally"; //return t; } } public static void main(String[] args) { System.out.print(TryCatchFinally.test()); } }
这个例子在catch语句块添加了Integer.parser(null)语句,强制抛出了一个异常。然后finally语句块里面没有return语句。继续分析一下,由于try语句抛出异常,程序进入catch语句块,catch语句块又抛出一个异常,说明catch语句要退出,则执行finally语句块,对t进行赋值。然后catch语句块里面抛出异常。结果是抛出java.lang.NumberFormatException异常
6:
public class TryCatchFinally { @SuppressWarnings("finally") public static final String test() { String t = ""; try { t = "try"; Integer.parseInt(null); return t; } catch (Exception e) { t = "catch"; Integer.parseInt(null); return t; } finally { t = "finally"; return t; } } public static void main(String[] args) { System.out.print(TryCatchFinally.test()); } }
这个例子和上面例子中唯一不同的是,这个例子里面finally 语句里面有return语句块。try catch中运行的逻辑和上面例子一样,当catch语句块里面抛出异常之后,进入finally语句快,然后返回t。则程序忽略catch语句块里面抛出的异常信息,直接返回t对应的值 也就是finally。方法不会抛出异常
7:
public class TryCatchFinally { @SuppressWarnings("finally") public static final String test() { String t = ""; try { t = "try"; Integer.parseInt(null); return t; } catch (NullPointerException e) { t = "catch"; return t; } finally { t = "finally"; } } public static void main(String[] args) { System.out.print(TryCatchFinally.test()); } }
这个例子里面catch语句里面catch的是NPE异常,而不是java.lang.NumberFormatException异常,所以不会进入catch语句块,直接进入finally语句块,finally对s赋值之后,由try语句抛出java.lang.NumberFormatException异常。
8:
public class TryCatchFinally { @SuppressWarnings("finally") public static final String test() { String t = ""; try { t = "try"; Integer.parseInt(null); return t; } catch (NullPointerException e) { t = "catch"; return t; } finally { t = "finally"; return t; } } public static void main(String[] args) { System.out.print(TryCatchFinally.test()); } }
和上面的例子中try catch的逻辑相同,try语句执行完成执行finally语句,finally赋值s 并且返回s ,最后程序结果返回finally
9:
public class TryCatchFinally { @SuppressWarnings("finally") public static final String test() { String t = ""; try { t = "try";return t; } catch (Exception e) { t = "catch"; return t; } finally { t = "finally"; String.valueOf(null); return t; } } public static void main(String[] args) { System.out.print(TryCatchFinally.test()); } }
这个例子中,对finally语句中添加了String.valueOf(null), 强制抛出NPE异常。首先程序执行try语句,在返回执行,执行finally语句块,finally语句抛出NPE异常,整个结果返回NPE异常。
对以上所有的例子进行总结
1 try、catch、finally语句中,在如果try语句有return语句,则返回的之后当前try中变量此时对应的值,此后对变量做任何的修改,都不影响try中return的返回值
2 如果finally块中有return 语句,则返回try或catch中的返回语句忽略。
3 如果finally块中抛出异常,则整个try、catch、finally块中抛出异常
所以使用try、catch、finally语句块中需要注意的是
1 尽量在try或者catch中使用return语句。通过finally块中达到对try或者catch返回值修改是不可行的。
2 finally块中避免使用return语句,因为finally块中如果使用return语句,会显示的消化掉try、catch块中的异常信息,屏蔽了错误的发生
3 finally块中避免再次抛出异常,否则整个包含try语句块的方法回抛出异常,并且会消化掉try、catch块中的异常