看了你就掌握---------JAVA中finally语句块的详解!!!!!

关于JAVA中finally语句块的详解

前言

相信同学们学习到面向对象的异常处理中应该会踩到finally语句块这个坑中,本篇博文通过各种案例帮你如何避免踩坑,踩雷,让你对异常处理的学习更加透彻,finally语句块掌握的更加扎实!


一、finally语句块的特点及应用场景

在进行异常处理时,finally语句块也在异常的处理格式中,finally语句块是整个异常处理的统一出口,不管是产生了异常还是未产生异常,那么finally语句块中的内容必然执行。

来一个小案例:

import java.lang.Exception;
public class Exception1 {
    public static void main(String[] args){
        int i = 10;
        int j = 0;
        try{
            System.out.println("输入的结果为" + i/j);
        }catch (Exception e ){
            System.out.println("动动你的脑筋,除数不能为0");
            return;
        }finally {
            System.out.println("finally语句执行了!");
        }
    }
}
运行结果:
	动动你的脑筋,除数不能为0
	finally语句执行了!

看完这段代码有人就有疑惑,为什么我在catch语句块中return了为什么后面的代码还会执行?

​ 因为我们在进行异常处理流程时,当catch语句块执行到return的时候,我们需要做准备return的操作,虽然这个返回值没有,但默认还是要把这个没有返回值的东西返回(可能有点绕,慢慢理解),在这个准备的过程中,我们就把finally语句块的内容执行了,执行完毕后,再return 结束掉这个方法。

二、finally语句块在任何情况一定会执行吗?

答案是:否!

第一种情况:JVM退出,finally不会执行。

import java.lang.Exception;
public class Exception2 {
    public static void main(String[] args){
        int i = 10;
        int j = 0;
        try{
            System.out.println("输入的结果为" + i/j);
        }catch (Exception e ){
            System.out.println("动动你的脑筋,除数不能为0")
            System.exit(1);// 退出JVM
        }finally {
            System.out.println("finally语句执行了!");
        }
    }
运行结果:
    动动你的脑筋,除数不能为0

​ 这种情况下,我们发现finally语句块并没有执行。因为我们在catch语句块中首先显示了错误信息,并退出了JAVA虚拟机,导致代码执行到此处,整个程序就结束了。

第二种情况:异常处理前结束方法,finally不会执行。

​ 这种情况是在进行异常处理前就return,结束了方法,那么后面的所有代码都不会执行,finally语句块也一定不会执行(编译器也不会让你写return之后的代码)。

第三种情况:在异常处理前,产生了其他的异常,finally不会执行。

public class Exception3 {
    public static void main(String[] args){
        int i = 10;
        int j = 0;
        System.out.println(i/j);
        try{
            System.out.println("try..........");
        }finally {
            System.out.println("finally.........");
        }
    }
}
运行结果:
	Exception in thread "main" java.lang.ArithmeticException: / by zero
		at kkb.Exception3.main(Exception3.java:6)

​ 这种情况是在处理异常前,产生了其他的异常,既出现异常,后面的代码不会执行,直接结束了方法。

三、finally和final的区别

​ 有很多同学不知道finally和final是干什么的,就像方法的重载和重写一样,都是名字差不多,但是它们的应用的场景完全不同,完全没有共同点。

​ finally:finally是一个语句块,是属于异常处理结构的成员之一,无论异常是否发生,finally语句块的内容一定输出,所以当我们需要编写无论发生什么都必须执行的代码时,就可以在finally语句块中。

​ final:final是一个关键字,可以修饰类、变量和方法,被final修饰的类不可以被派生出新的子类。被final修饰的方法不能被重写,不能修改方法中的内容。被fianl修饰的变量只能赋一次值,通常用fianl来修饰常量:public abstract final int +变量名。

四、finally常见踩坑面试题目

​ finally主要分为以下两种题型,掌握了思想,那么所有题目迎刃而解。

第一个案例:

class Person{	//创建一个Person类
    int age;	//属性有age
}
public class Exception4 {
    public static void main(String[] args){
        Person p = p(); //调用p方法
        System.out.println(p.age); //输入age的值
    }
    public static Person p(){
        Person p = new Person(); //创建Person对象
        p.age = 0;	//将默认值设为0
        try{
            p.age = 18;
            return p;
        }catch (Exception e){
            p.age = 10;
            return p;
        }finally {
            p.age = 20;
        }
    }
}
运行结果:
	20

题解:

​ 首先先分析流程 我们在try语句块中将p.age设置为了18,然后返回这个对象,因为我们没有设置年龄的限制,所以catch语句块的内容一定不会执行。

​ 当代码执行进入try语句块时,首先将p.age设置为18,然后进入return p语句,在执行这段代码时,我们可以理解为先复制了这个p的内存地址,然后进入finally语句块中,将p.age设置为了20,然后再将这个p保存的内存地址返回。因为在堆对象中,这个p.age被finally语句块改变,所以在返回的p中包含的已被修改后的p.age的值。所以最终打印的结果为20;

重点:当返回的数据时引用数据类型时,返回的是该对象的内存地址!!!

第二个案例:

public class Exception5 {
    public static void main(String[] args){
        int code = i();
        System.out.println(code);
    }
    public static int i(){
        int i = 0;
        try{
            return i;
        }finally {
            i = 20;
        }
    }
}
运行结果:
	0

题解:

​ 首先分析流程,在i()方法中我们先定义了个基本数据类型的变量i =0,在try语句块中返回了这个i,在finally语句块中修改了i的值。大家可能会认为,在try语句的return返回之前应该先执行finally语句块,修改完毕后再返回吗。最后输出结果应该是20才对。

​ 流程:我们在return语句返回这个i之前,首先先把i的值(数据0)复制一份,然后进入finally语句块,我们把i修改为20,然后再执行return,那么return返回的仍然是这个复制好的数据。所以输出是0;

总结两道案例:

​ 这两道案例一个返回的基本数据类型,一个是返回的引用数据类型。

区别:

​ 引用数据类型存储的数据在堆中,执行完finally语句后,返回的是这个对象的内存地址复制,内存地址再指向对象,如果对象中的数据被改变,那么内存地址指向的这个对象也会发生改变。

​ 局部变量中基本数据类型的数据存储在栈中,执行完finally语句后,返回的是这个数据本身的复制,如果数据被改变,那么返回内容则不变。

总结

     以上就是今天要讲的内容,本文讲解了finally语句块的执行流程,通过一个个案例来告诉同学们在各种场景下的finally语句块该如何执行的问题,希望能帮助到在此知识点上模糊的同学。
     觉得有帮助的同学来个三连哦!
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值