Java finally和return的执行顺序(非常重要)

在 Java 的异常处理中,try、catch 和 finally 是按顺序执行的。如果 try 中没有异常,则顺序为 try→finally,如果 try 中有异常,则顺序为 try→catch→finally。但是当 try、catch、finally 中加入 return 之后,return 和 finally 的执行顺序让很多人混淆不清。下面来分别说明一下。

1. try 和 catch 中带有 return

1)try 中带有 return

public class tryDemo 
{
    public static int show() 
    {
        try {
            return 1;
        } finally {
            System.out.println("执行finally模块");
        }
    }

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

输出结果如下:

执行finally模块
1

2)try 和 catch 中都带有 return 

public class tryDemo 
{
    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

当 try 代码块或者 catch 代码块中有 return 时,finally 中的代码总会被执行,且 finally 语句 return 返回之前执行。

注意:可以使用编译器的 Debug 功能查看详细过程。如果不了解如何使用 Debug 功能可参考《Java Eclipse如何调试代码》一节。

2. finally 中带有 return

public class tryDemo 
{
    public static int show() 
    {
        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());
    }
}

输出结果如下:

执行finally模块
0

当 finally 有返回值时,会直接返回该值,不会去返回 try 代码块或者 catch 代码块中的返回值。

注意:finally 代码块中最好不要包含 return 语句,否则程序会提前退出。

3. finally 中改变返回值

下面先来看 try 代码块或者 catch 代码块中的返回值是普通变量时,代码如下:

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

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

输出结果为:

执行finally模块
0

由输出结果可以看出,在 finally 代码块中改变返回值并不会改变最后返回的内容。

当返回值类型是引用类型时,结果也是一样的,代码如下:

public class tryDemo 
{
    public static Object show() 
    {
        Object obj = new Object();
        try {
            return obj;
        } finally {
            System.out.println("执行finally模块");
            obj = null;
        }
    }

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

输出结果为:

执行finally模块
java.lang.Object@15db9742

当 try 代码块或 catch 代码块中的 return 返回值类型为普通变量或引用变量时,即使在后面 finally 代码块中对返回值的变量重新赋值,也不会影响最后返回的值。

总结为以下几条:

1、当 try 代码块和 catch 代码块中有 return 语句时,finally 仍然会被执行。

2、执行 try 代码块或 catch 代码块中的 return 语句之前,都会先执行 finally 语句。

3、无论在 finally 代码块中是否修改返回值,返回值都不会改变,仍然是执行 finally 代码块之前的值。

4、finally 代码块中的 return 语句一定会执行。