有这样一个问题,异常处理大家应该都不陌生,类似如下代码:

 public class Test {
public static void main(String[] args) {
int d1 = 0;
int d2 = 1;
try {
d2--;
d1 = 1 / d2;
System.out.println("try");
}catch (Exception e){
System.out.println("Catch An Exception.");
}finally {
System.out.println("finally");
}
}
}

  运行到第7行的时候,会出现算术异常,try语句块捕获到这个异常,然后开始执行catch语句块中的内容,最后执行,finally语句块中的内容,因此输出如下:

Catch An Exception.
finally

  但是,如果try,catch,finally语句中有return的时候,会怎样呢?

  我们都知道,finally语句块是不论如何都会执行的,那三个块中的return,会先返回谁呢?我们来进行一下测试:

public class Test {
public static void main(String[] args) {
int i = Test.getReturn();
System.out.println(i); } public static int getReturn(){
int a = 0;
int d1 = 0;
int d2 = 1;
try {
      //try语句块中没有发生异常
a = 10;
d1 = 1 / d2;
return a;
}catch (Exception e){
a = 20;
System.out.println("Catch An Exception.");
return a;
}finally {
a = 30;
System.out.println("finally");
return a;
}
}
}

  这里的try语句块中没有发生异常,那么执行顺序如何呢?在try中的return是直接返回吗?finally的return该怎样处理呢?先让我们看一下结果:

finally
30

  结果是执行完成finally语句块之后,使用的是finally语句块中的a,而不是try语句块中的a。

  那如果try中出现异常呢?我们改动一下:

public class Test {
public static void main(String[] args) {
int i = getReturn();
System.out.println(i); } public static int getReturn(){
int a = 0;
int d1 = 0;
int d2 = 1;
try {
a = 10;
d1 = 1 / (--d2);
return a;
}catch (Exception e){
a = 20;
System.out.println("Catch An Exception.");
return a;
}finally {
a = 30;
System.out.println("finally");
return a;
}
}
}

  好的,现在try中出现了算术异常,catch语句块将被执行,然后再执行finally语句块,这样的话返回结果如何呢?

Catch An Exception.
finally
30

  还是返回30,也就是finally中a的值

  如果去掉finally中的return会怎样?

public class Test {
public static void main(String[] args) {
int i = getReturn();
System.out.println(i); } public static int getReturn(){
int a = 0;
int d1 = 0;
int d2 = 1;
try {
a = 10;
d1 = 1 / (--d2);
return a;
}catch (Exception e){
a = 20;
System.out.println("Catch An Exception.");
return a;
}finally {
a = 30;
System.out.println("finally");
//return a;
}
}
}

  输出如下:

Catch An Exception.
finally
20

  返回的是catch语句块中的a。先执行catch语句块中的代码,finally语句虽然执行了,a的值应该也被修改成30了,但实际返回的却是20,。

  我们再来做一个测试,把catch和finally语句块中的return都注释掉,来看看返回情况:

public class Test {
public static void main(String[] args) {
int i = getReturn();
System.out.println(i); } public static int getReturn(){
int a = 0;
int d1 = 0;
int d2 = 1;
try {
a = 10;
d1 = 1 / (d2);
return a;
}catch (Exception e){
a = 20;
System.out.println("Catch An Exception.");
//return a;
}finally {
a = 30;
System.out.println("finally");
//return a;
}
return a;
}
}

  输出如下:

finally
10

  所以finally中虽然修改了a的值,但实际返回的是修改之前的值。也就是相当于程序先用一个瓶子将try中的return的值装起来,后面不管finally如果修改a的值,返回值都不会变,但这只是因为返回的是基本数据类型,如果是引用类型,还是有点区别的,来看个栗子。

  先声明一个Stu类:

public class Stu {
String name; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} }

  测试一下:

public class Test {
public static void main(String[] args) {
Stu stu = getReturn();
System.out.println(stu.getName()); } public static Stu getReturn(){
Stu stu = new Stu();
int d1 = 0;
int d2 = 1;
try {
stu.setName("1");
d1 = 1 / (d2);
return stu;
}catch (Exception e){
stu.setName("2");
System.out.println("Catch An Exception.");
}finally {
stu.setName("3");
System.out.println("finally");
}
return stu;
}
}

  输出如下:

finally
3

  所以你看,现在还是变成了finally中的修改值,所以瓶子里装的只是变量中的内容,只能保证这个内容不会变,如果是引用变量,变量中存储的是引用对象的地址,finally中对引用对象的修改还是会影响到返回对象的。

  所以结论其实很简单,try,catch,finally语句块的return的优先级由低到高,先执行try中return之前的语句,如果遇到异常,则执行catch语句中return之前的代码,最后执行finally语句块,finally语句块中如果有return,那么程序就会提前返回,如果没有,则返回catch语句块中的return,如果没有遇到异常,则直接执行finally中的语句块,再看finally语句块中是否有return来决定返回结果。

  结论:
  1、不管是否出现异常,finally块中的代码都会执行;
  2、当try和catch中有return时,finally仍然会执行,finally中的return优先级大于catch大于try;
  3、finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,管finally中的代码怎么样,返回的值都不会改变,任然是之前保存的值),所以函数返回值是在finally执行前确定的;
  4、finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值。

【Java疑难杂症】有return的情况下try catch finally的执行顺序的更多相关文章

  1. Java基础知识强化之IO流笔记06:有return的情况下try catch finally的执行顺序

    1. 给出结论: (1)不管有木有出现异常,finally块中代码都会执行:(2)当try和catch中有return时,finally仍然会执行:(3)finally是在return后面的表达式运算 ...

  2. 有return的情况下try catch finally的执行顺序(转)

    结论:1.不管有木有出现异常,finally块中代码都会执行:2.当try和catch中有return时,finally仍然会执行:3.finally是在return后面的表达式运算后执行的(此时并没 ...

  3. 有return的情况下try catch finally的执行顺序

    结论:1.不管有木有出现异常,finally块中代码都会执行:2.当try和catch中有return时,finally仍然会执行:3.finally是在return后面的表达式运算后执行的(此时并没 ...

  4. 有return的情况下try catch finally的执行顺序(最有说服力的总结)

    结论:1.不管有木有出现异常,finally块中代码都会执行:2.当try和catch中有return时,finally仍然会执行:3.finally是在return后面的表达式运算后执行的(此时并没 ...

  5. 有return的情况下try catch finally的执行顺序(转)

    结论:1.不管有没有出现异常,finally块中代码都会执行:2.当try和catch中有return时,finally仍然会执行:3.finally是在return后面的表达式运算后执行的(此时并没 ...

  6. [转]有return的情况下try catch finally的执行顺序

    结论: 1.不管有没有出现异常,finally块中代码都会执行: 2.当try和catch中有return时,finally仍然会执行: 3.finally是在return后面的表达式运算后执行的(此 ...

  7. throw和throws的区别以及try,catch,finally在有return的情况下执行的顺序

    一,抛出异常有三种形式,一是throw,一个throws,还有一种系统自动抛异常.下面它们之间的异同. (1).系统自动抛异常 1.当程序语句出现一些逻辑错误.主义错误或类型转换错误时,系统会自动抛出 ...

  8. 【转】C# 异常处理 throw和throw ex的区别 try catch finally的执行顺序(return)

    [转]throw和throw ex的区别 之前,在使用异常捕获语句try...catch...throw语句时,一直没太留意几种用法的区别,前几天调试程序时无意中了解到几种使用方法是有区别的,网上一查 ...

  9. Java之HashMap在多线程情况下导致死循环的问题

    PS:不得不说Java编程思想这本书是真心强大.. 学习内容: 1.HashMap<K,V>在多线程的情况下出现的死循环现象   当初学Java的时候只是知道HashMap<K,V& ...

随机推荐

  1. NSTimer的问题

    iOS开发中,涉及到定时的问题,我们通常使用NSTimer来解决,例如下面的代码. SFClass.h #import <Foundation/Foundation.h> @interfa ...

  2. vue-cli 自定义指令directive 添加验证滑块

    vue项目注册登录页面遇到了一个需要滑块的功能,网上看了很多插件发现都不太好用,于是自己写了一个插件供大家参考: 用的是vue的自定义指令direcive,只需要在需要的组件里放入对应的标签嵌套即可: ...

  3. 上传代码 CodePlex

    博客园作为博客备份,博客会更新一份在博客园 CodePlex是微软开源项目网站,有很多人都在上面传代码,我们也可以上传自己的代码 注册 我们可以用微软账号注册,填写用户名.密码,很快就好. 新建项目 ...

  4. Httpd2.2常见配置及功能

    Httpd 2.2常见配置 要配置http服务的配置文件,先备份一下,养成良好习惯,如果误操作导致http服务起不来,就可以将备份的主配置文件重新覆盖一下 httpd配置文件的组成:有三大部分组成,其 ...

  5. 正六边形网格化(Hexagonal Grids)原理与实现

    在路径规划.游戏设计栅格法应用中,正六边形网格不如矩形网格直接和常见,但是正六边形具有自身的应用特点,更适用于一些特殊场景中,比如旷阔的海洋.区域或者太空.本文主要讲述如何对正六边形进行几何学分析.网 ...

  6. C 其他一些

    1.联合,语法 union{成员1;成员2;} 联合间的成员共享同一个空间,也就是说,成员1赋值如果没有被清除,会体现在成员2上 2.位字段,结合结构体瓜分完整的类型存储空间,如 struct{ ; ...

  7. 关于echarts、layer.js和jqGrid的知识点

    使用echarts和layer.js直接去官方文档,能解决大部分问题. 但是有些问题,解释不够清楚,在这里记录一下. 1.echarts的使用 第一点:关于echarts的labelline在数据为零 ...

  8. Linux系列教程(六)——Linux文件搜索命令

    前一篇博客我们讲解了Linux链接命令和权限管理命令, 通过 ln -s  链接名 表示创建软链接,不加-s表示创建硬链接:还有三个更改权限的命令,chmod命令可以更改文件或目录权限,chown命令 ...

  9. java时间格式

    Calendar startdate = Calendar.getInstance(); startdate.setTime(new Date()); //当前时间 startdate.add(Cal ...

  10. Ant 基本语法的使用示列

    ant -f build.xml  执行你的build.xml文件   <?xml version = "1.0"?> <project name = " ...