finally

1.finally概述

finally是try+catch标准处理格式的 异常的统一出口。只有程序停止(内存层面上:如关机,调用System.exit(0)等),finally中的语句才不会被执行;其他任何情况下,finally中的语句都必然被执行

try{
     
// 有可能发生异常的代码段 
}catch(异常类型1 对象名1){
      
// 异常的处理操作 
}catch(异常类型2 对象名2){
     
// 异常的处理操作 
} ... finally{
     
 // 异常的统一出口 
}

2.对上述内容的举例证明(面试题)

(1)return不会中止finally中的内容

代码:

public class Test1 {
     
    public static void main(String[] args) {
     
        test();
    }
    
    public static void test() {
     
        try {
     
            System.out.println(1);
            System.out.println(2);
            System.out.println(3);
            System.out.println(4);
            return;
        } catch (Exception e) {
     
            
        } finally {
     
            System.out.println("finally中的内容执行了");
        }
    }
}

运行结果:

1
2
3
4
finally中的内容执行了

分析:return是终止方法运行,但是return是有个返回过程的,就算是无返回值类型,return也会向方法返回一个“无返回值的返回值” ;而finally中的语句就是在return返回的过程中执行的

(2)System.exit(0)会中止finally中的内容

代码:

public class Test1 {
     
    public static void main(String[] args) {
     
        test();
    }
    
    public static void test() {
     
        try {
     
            System.out.println(1);
            System.out.println(2);
            System.out.println(3);
            System.out.println(4);
            // 退出JVM
            System.exit(0);
        } catch (Exception e) {
     
            
        } finally {
     
            System.out.println("finally中的内容执行了");
        }
    }
}

运行结果:

1
2
3
4

分析:执行System.exit(0);直接退出JVM,直接在内存上结束了程序

(3)finally中修改引用数据类型和基本数据类型数值的解析

①finally中修改引用数据类型数值

代码:

public class Test1 {
     
    public static void main(String[] args) {
     
        Person p = test();
        System.out.println(p.age);
    }
    
    public static Person test() {
     
        Person p = new Person();
        try {
     
            p.age = 18;
            return p;
        } catch (Exception e) {
     
            return null;
        } finally {
     
            p.age = 28;
            System.out.println("finally中的内容执行了");
        }
        
    }
    static class Person {
     
        int age;
    }
}

运行结果

finally中的内容执行了
28

②finally中修改基本数据类型数值

代码:

public class Test1 {
     
    public static void main(String[] args) {
     
        System.out.println(test());
    }
    
    public static int test() {
     
        int i = 10;
        try {
     
            return i;
        } catch (Exception e) {
     
            return 0;
        } finally {
     
            System.out.println("finally中的内容执行了");
            i = 20;
        }
        
    }
}

运行结果:

finally中的内容执行了
10
①和②结合分析
看到这里可能有人就迷惑了,不是说finally里的内容必然会执行吗?为什么 i 的值还是10,没有发生变化?难道是没执行吗?

其实不是。首先我们要了解return返回的一点细节:return返回时不是讲你所看到 i 或者 p 直接返回的,而是将其先备份,然后返回其备份值。
然后我们再来看这两个例子(自己画内存分析图更容易理解):
①中,p 中存储着Person的堆内存地址,在即将return之前,系统备份了 p 指向Person的地址,并在finally执行完毕后将备份数据返回,然后p.age = 28;进行return,此时,虽然备份的数据保持不变,但是通过 p 可以访问到变化后的age。
②中,i 直接存储着整型数据10,在即将return之前,系统备份了 i 中的数据10,并在finally执行完毕后将备份数据返回,然后 i = 20;进行return,此时,返回的是备份的10,而不是20。

你可能感兴趣的:(java)