Java 中 finally 和 return 顺序问题

222 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第22天,点击查看活动详情

其实return与finally并没有明显的谁强谁弱。在执行时,是return语句先把返回值写入但内存中,然后停下来等待finally语句块执行完,return再执行后面的一段。

  • finally:异常代码块中,最后都会执行的代码。通常用来关闭资源。
  • return:用于跳出当前方法,指针返回值。

case1 try 中有 return,finally 中无 return。

public class main {
    public static int show() {
        try {
            return 1;
        }finally{
            System.out.println("finally模块被执行");
        }
    }
    public static void main(String args[]) {
        System.out.println(show());
    }
}

执行结果:

finally模块被执行
1

finally 中前面有 return ,finally 中也会执行。

case2:finallyreturn,try 中有return ,catch 中也有 return

public static int show() {
        try {
            int a = 8 / 0;
            return 1;
        } catch (Exception e) {
            return 2;
        } finally {
            System.out.println("finally模块被执行");
        }
    }

    public static void main(String[] args) {
        System.out.println(show());
    }

输出结果:

finally模块被执行
2

可以理解 return 先把结果缓存起来,finally 执行完成后,再返回 return 值。

case3:try,finally,catch 中都有 return 的值

    public static int show_1() {
        try {
            int a = 8 / 0;
            return 1;
        } catch (Exception e) {
            return 2;
        } finally {
            System.out.println("finally模块被执行");
            return 0;
        }
    }
    public static void main(String[] args) {
//        System.out.println(show());
        System.out.println(show_1());
    }

执行结果

finally模块被执行
0

可看到执行结果中还是先 finallyreturn

case4:如果 在 finally 中改变 reuturn 内容

   public static int show_2() {
        int result = 0;
        try {
            return result;
        } finally {
            System.out.println("finally模块被执行");
            result = 1;
        }
    }

    public static void main(String[] args) {
//        System.out.println(show());
//        System.out.println(show_1());
        System.out.println(show_2());
    }

执行结果:

finally模块被执行
0

case5: return 基本类型,如果return 的值时引用变量,finally 中改变return的值,会改变输出

测试代码:

public class TestTryCatch {
    public static void main(String[] args)
    {
        TestTryCatch test = new TestTryCatch();
        System.out.println(test.fun());
    }

    public StringBuilder fun()
    {
        StringBuilder s = new StringBuilder("Hello");
        try
        {
            //doing something
            s.append("Word");

            return s;
        }catch(Exception e){
            return s;
        }finally{
            string.append("finally");
        }
    }
}

输出结果:

HelloWordFinally

当返回值不是基本数据类型的时候,其是指向一段内存的,return将返回段指向一段内存,但是代码段的s依然是指向的同一段内存地址,所以当s修改它指向内存中的值的时候,其实也就修改了返回段指向内存中的值,所以最终的值改变了。

如果 finally 中是引用对象, finally 修改了return 的值 ,比如设置 null ,时无效的。

  public static Object show_3() {
        String obj = new String("HelloWord");
        try {
            return obj;
        } finally {
            System.out.println("finally模块被执行");
            obj = null;
        }
    }

    public static void main(String[] args) {
//        System.out.println(show());
//        System.out.println(show_1());
//        System.out.println(show_2());
        System.out.println(show_3());
    }

测试结果:

finally模块被执行
HelloWord