首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

深入理解final关键字(详解)

  • 25-03-07 20:40
  • 3084
  • 11700
blog.csdn.net

提及final关键字都会想到一个常见的面试题就是:
final、finally、finalize区别
在这里我们来简单回忆一下这三者的区别,

  • final: Final用于修饰类、成员变量和成员方法。final修饰的类,不能被继承(String、StringBuilder、StringBuffer、Math,不可变类),其中所有的方法都不能被重写(这里需要注意的是不能被重写,但是可以被重载,这里很多人会弄混),所以不能同时用abstract和final修饰类(abstract修饰的类是抽象类,抽象类是用于被子类继承的,和final起相反的作用);Final修饰的方法不能被重写,但是子类可以用父类中final修饰的方法;Final修饰的成员变量是不可变的,如果成员变量是基本数据类型,初始化之后成员变量的值不能被改变,如果成员变量是引用类型,那么它只能指向初始化时指向的那个对象,不能再指向别的对象,但是对象当中的内容是允许改变的。

我们来深入理解一下被final修饰的类、方法、变量

  1. final修饰的类
    在这里插入图片描述

可以看到 被final修饰的类被继承编译器就直接报错了,如果去掉final
在这里插入图片描述
就没有问题

那这里就有一个问题了,为什么设计了继承还要有final来破坏这种继承关系呢。
这个解释在《Java编程思想》说的比较清楚:
使用 final 方法的原因有两个。第一个原因是把方法锁定,以防任何继承类修改它的含义;第二个原因是效率。在早期的Java实现版本中,会将final方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升。在最近的 Java 版本中,不需要使用 final 方法进行这些优化了。“

  1. 被final修饰的变量

我们来看一个有意思的代码

public class Main {
   public static void main(String[] args) {
       String a = "xiaomeng2";
       final String b = "xiaomeng";
       String d = "xiaomeng";
       String c = b + 2;
       String e = d + 2;
       System.out.println((a == c));
       System.out.println((a == e));
   }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

这段代码的输出结果是什么呢?
答案是: true 和 false
原因:

  1. 变量a指的是字符串常量池中的 xiaomeng2;
  2. 变量 b 是 final 修饰的,变量 b 的值在编译时候就已经确定了它的确定值,换句话说就是提前知道了变量 b 的内容到底是个啥,相当于一个编译期常量;
  3. 变量 c 是 b + 2得到的,由于 b 是一个常量,所以在使用 b 的时候直接相当于使用 b 的原始值(xiaomeng)来进行计算,所以 c 生成的也是一个常量,a 是常量,c 也是常量,都是 xiaomeng2 而 Java 中常量池中只生成唯一的一个 xiaomeng2 字符串,所以 a 和 c 是相等的!
  4. d 是指向常量池中 xiaomeng,但由于 d 不是 final 修饰,也就是说在使用 d 的时候不会提前知道 d 的值是什么,所以在计算 e 的时候就不一样了,e的话由于使用的是 d 的引用计算,变量d的访问却需要在运行时通过链接来进行,所以这种计算会在堆上生成 xiaomeng2 ,所以最终 e 指向的是堆上的 xiaomeng2 , 所以 a 和 e 不相等。
    总得来说就是:a、c是常量池的xiaomeng2,e是堆上的xiaomeng2

然后我们来看一下被final修饰的引用变量和基本变量有什么不同:

我们看基本变量
在这里插入图片描述
可以看到 基本变量使用final修饰了就不可变了

对于引用变量被final修饰了:引用变量引用不可变,但是引用对象的内容可以改变。
在这里插入图片描述
可以看到使用final修饰了的类不能再指向别处
如何理解内容可变呢:
在这里插入图片描述
可以看到这里类的属性a的值是能够改变的

然后我们总结一下使用final关键字的好处:

  1. final方法比非final快一些
  2. final关键字提高了性能。JVM和Java应用都会缓存final变量。
  3. final变量可以安全的在多线程环境下进行共享,而不需要额外的同步开销。
  4. 使用final关键字,JVM会对方法、变量及类进行优化。
  • Finally:

通常和try catch搭配使用,保证不管有没有发生异常,资源都能够被释放(释放连接、关闭IO流)

当try中有return时执行顺序:return语句并不是函数的最终出口,如果有finally语句,这在return之后还会执行finally(return的值会暂存在栈里面,等待finally执行后再返回)

  • 情况一(try中有return,finally中没有return)

在这里插入图片描述

“return num += 80”被拆分成了“num = num+80”和“return num”两个语句,线执行try中的“num =num+80”语句,将其保存起来,在try中的”return num“执行前,先将finally中的语句执行完,而后再将90返回。

  • 情况二(try和finally中均有return)

在这里插入图片描述

try中的return被”覆盖“掉了,不再执行。

  • 情况三(finally中改变返回值num)

在这里插入图片描述

虽然在finally中改变了返回值num,但因为finally中没有return该num的值,因此在执行完finally中的语句后,test()函数会得到try中返回的num的值,而try中的num的值依然是程序进入finally代码块前保留下来的值,因此得到的返回值为10。并且函数最后面的return语句不会执行。

  • 另外一种情况:将num的值包装在Num类中

在这里插入图片描述

总结:

try语句在返回前,将其他所有的操作执行完,保留好要返回的值,而后转入执行finally中的语句,而后分为以下三种情况:

情况一:如果finally中有return语句,则会将try中的return语句”覆盖“掉,直接执行finally中的return语句,得到返回值,这样便无法得到try之前保留好的返回值。

情况二:如果finally中没有return语句,也没有改变要返回值,则执行完finally中的语句后,会接着执行try中的return语句,返回之前保留的值。

情况三:如果finally中没有return语句,但是改变了要返回的值,这里有点类似与引用传递和值传递的区别,分以下两种情况:
如果return的数据是基本数据类型,则在finally中对该基本数据的改变不起作用,try中的return语句依然会返回进入finally块之前保留的值。
如果return的数据是引用数据类型,而在finally中对该引用数据类型的属性值的改变起作用,try中的return语句返回的就是在finally中改变后的该属性的值。


  • Finalize:

Finalize是object类中的一个方法,子类可以重写finalize()方法实现对资源的回收。垃圾回收只负责回收内存,并不负责资源的回收,资源回收要由程序员完成,Java虚拟机在垃圾回收之前会先调用垃圾对象的finalize方法用于使对象释放资源(如关闭连接、关闭文件),之后才进行垃圾回收,这个方法一般不会显示的调用,在垃圾回收时垃圾回收器会主动调用。

博客借鉴:
https://blog.csdn.net/CSDN_bang/article/details/86851078
https://blog.csdn.net/stypace/article/details/42102181

关于我

​ 觉得文章不错请扫码关注我吧

​ weichat

小奏技术
微信公众号
专注原创,源码爱好者,分享实用技术
注:本文转载自blog.csdn.net的weihubeats的文章"https://weihubeats.blog.csdn.net/article/details/87708198"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top