当前位置: 首页 > 编程日记 > 正文

3.1、final、finally、 finalize

final 可以用来修饰类、方法、变量,分别有不同的意义,final 修饰的 class 代表不可以继承扩展,final 的变量是不可以修改的,而 final 的方法也是不可以重写的(override)。

finally 则是 Java 保证重点代码一定要被执行的一种机制。我们可以使用 try-finally 或者 try-catch-finally 来进行类似关闭 JDBC 连接、保证 unlock 锁等动作。

finalize 是基础类 java.lang.Object 的一个方法,它的设计目的是保证对象在被垃圾收集前完成特定资源的回收。finalize 机制现在已经不推荐使用,并且在 JDK 9 开始被标记为 deprecated。

面试官还可以考察你对性能、并发、对象生命周期或垃圾收集基本过程等方面的理解。

final 关键字来明确表示我们代码的语义、逻辑意图,这已经被证明在很多场景下是非常好的实践,比如:

  • 我们可以将方法或者类声明为 final,这样就可以明确告知别人,这些行为是不许修改的。

如果你关注过 Java 核心类库的定义或源码, 有没有发现 java.lang 包下面的很多类,相当一部分都被声明成为 final class?在第三方类库的一些基础类中同样如此,这可以有效避免 API 使用者更改基础功能,某种程度上,这是保证平台安全的必要手段。

  • 使用 final 修饰参数或者变量,也可以清楚地避免意外赋值导致的编程错误,甚至,有人明确推荐将所有方法参数、本地变量、成员变量声明成 final。

  • final 变量产生了某种程度的不可变(immutable)的效果,所以,可以用于保护只读数据,尤其是在并发编程中,因为明确地不能再赋值 final 变量,有利于减少额外的同步开销,也可以省去一些防御性拷贝的必要。

finally,明确知道怎么使用就足够了。需要关闭的连接等资源,更推荐使用 Java 7 中添加的

try-with-resources(https://www.cnblogs.com/hihtml5/p/6505317.html 语句,因为通常 Java 平台能够更好地处理异常情况,编码量也要少很多,何乐而不为呢。

a、try-cach 异常退出,下面 finally 里面的代码可不会被执行,这是一个特例。

try {// do somethingSystem.exit(1);
} finally{System.out.println(“Print from finally”);
}

b,无限循环时, finally 里面的代码也不会被执行

try{
  while(ture){
    print(abc);
  }
} finally {
  System.out.println(“Print from finally”);

}

c、 线程被杀死时,当执行 try,finally 的线程被杀死时。finally 也无法执行。

finalize,我们要明确它是不推荐使用的,业界实践一再证明它不是个好的办法,在 Java 9 中,甚至明确将 Object.finalize() 标记为 deprecated!如果没有特别的原因,不要实现 finalize 方法,也不要指望利用它来进行资源回收。你无法保证 finalize 什么时候执行,执行的是否符合预期。使用不当会影响性能,导致程序死锁、挂起等。通常来说,利用上面的提到的 try-with-resources 或者 try-finally 机制,是非常好的回收资源的办法。如果确实需要额外处理,可以考虑 Java 提供的 Cleaner 机制或者其他替代方法。

实践中注意:

1.final 不是 immutable(不可变的)

final List<String> strList = new ArrayList<>();strList.add("Hello");strList.add("world");  List<String> unmodifiableStrList = List.of("hello", "world");unmodifiableStrList.add("again");

final 只能约束 strList 这个引用不可以被赋值,但是 strList 对象行为不被 final 影响,添加元素等操作是完全正常的。如果我们真的希望对象本身是不可变的,那么需要相应的类支持不可变的行为。在上面这个例子中,List.of 方法创建的本身就是不可变 List,最后那句 add 是会在运行时抛出异常的。

(final修饰引用类型的话,引用值不能被修改。但是引用值指向的内容可以被修改,这样看来修饰引用类型并不是线程安全的?)

不可变在很多场景是非常棒的选择,某种意义上说,Java 语言目前并没有原生的不可变支持,如果要实现 immutable 的类,我们需要做到:

  • 将 class 自身声明为 final,这样别人就不能扩展来绕过限制了。

  • 将所有成员变量定义为 private 和 final,并且不要实现 setter 方法。

  • 通常构造对象时,成员变量使用深度拷贝来初始化,而不是直接赋值,这是一种防御措施,因为你无法确定输入对象不被其他人修改。

  • 如果确实需要实现 getter 方法,或者其他可能会返回内部状态的方法,使用 copy-on-write 原则,创建私有的 copy。

关于 setter/getter 方法,很多人喜欢直接用 IDE 一次全部生成,建议最好是确定有需要时再实现。

2.finalize

finalize 的执行是和垃圾收集关联在一起的,一旦实现了非空的 finalize 方法,就会导致相应对象回收呈现数量级上的变慢。因为,finalize 被设计成在对象被垃圾收集前调用,这就意味着实现了 finalize 方法的对象是个“特殊公民”,JVM 要对它进行额外处理。finalize 本质上成为了快速回收的阻碍者,可能导致你的对象经过多个垃圾收集周期才能被回收。实践中,因为 finalize 拖慢垃圾收集,导致大量对象堆积,也是一种典型的导致 OOM 的原因。

我们要确保回收资源就是因为资源都是有限的,垃圾收集时间的不可预测,可能会极大加剧资源占用。这意味着对于消耗非常高频的资源,千万不要指望 finalize 去承担资源释放的主要职责,最多让 finalize 作为最后的“守门员”,况且它已经暴露了如此多的问题。这也是为什么我推荐,资源用完即显式释放,或者利用资源池来尽量重用。

Java 平台目前在逐步使用 java.lang.ref.Cleaner 来替换掉原有的 finalize 实现。Cleaner 的实现利用了幻象引用(PhantomReference),这是一种常见的所谓 post-mortem 清理机制。利用幻象引用和引用队列,我们可以保证对象被彻底销毁前做一些类似资源回收的工作,比如关闭文件描述符(操作系统有限的资源),它比 finalize 更加轻量、更加可靠。吸取了 finalize 里的教训,每个 Cleaner 的操作都是独立的,它有自己的运行线程,所以可以避免意外死锁等问题。注意,从可预测性的角度来判断,Cleaner 或者幻象引用改善的程度仍然是有限的,如果由于种种原因导致幻象引用堆积,同样会出现问题。所以,Cleaner 适合作为一种最后的保证手段,而不是完全依赖 Cleaner 进行资源回收,不然我们就要再做一遍 finalize 的噩梦了。

finalize本身就是为了提供类似c或c++析构函数产生的,由于java中gc本身就是自动进行的,是不希望被干扰的,(就像System.gc(),并不一定起作用)所以与其费心研究如何使用这个,不如老老实实在finally中把该做的事情做了来的实惠。

转载于:https://www.cnblogs.com/xuan5301215/p/9019078.html

相关文章:

Android模拟器学framework和driver之传感器篇1(linux sensor driver)

对于android模拟器开发环境的搭建这里我就不多说了&#xff0c;网上google下一大堆&#xff0c;还有就是android 模拟器的kernel使用的是goldfish的kernel&#xff0c;可以使用git得到源码&#xff0c;然后就可以编译了&#xff0c;大家还是可以参考罗老师的博客。。。 在这里我…

【java】Lombok的使用

介绍&#xff1a;lombok在编译entity文件时自动生成get set toString hashCode等方法&#xff0c;这样方法生成就不用写在代码里了&#xff0c;可以简化代码。 使用方法&#xff1a; 一、在pom文件里引入lombok的依赖 代码实现&#xff1a; <dependency><groupId&g…

自己开发开源jquery插件--给jquery.treeview加上checkbox

很多时候需要把树状的数据显示除来&#xff0c;比如分类&#xff0c;中国省份、城市信息&#xff0c;等&#xff0c;因此这方面的javascript插件也有很多.比如性能优异的jquery.treeview和国人开发的功能强大的zTree. 我最近在一个项目中用到了jquery.treeview&#xff0c;但是…

SQL Server 2000安装时不出现安装界面,进程中存在解决

在XP和Server 2003系统中安装SQL Server 2000过程中&#xff0c;点击安装后&#xff0c;一直不出现安装界面&#xff0c;查看进程中也有&#xff0c;一直无反应。 解决办法&#xff1a; 首先重新启动机器&#xff0c;或者任务管理器里面结束2个sql进程 1. 在 SQLServer 安装向导…

Apache2.4部署python3.6+django2.0项目

一、安装apache Apache是非常有名的web服务器软件&#xff0c;如果想让我们web项目运行几乎离不开它。 Apache官方网站&#xff1a;http://httpd.apache.org/ 根据自己的环境&#xff0c;选择相应的版本进行下载。apache 官网没有windows 64位版本&#xff0c;可以通过下面的链…

我是如何有效的避免测试漏测?

漏测&#xff0c;指在产品缺陷在测试过程中没有被发现&#xff08;尤其是测试环境可以重现的缺陷&#xff09;&#xff0c;而是在版本发布后或者在用户使用后发现并反馈回来的缺陷。可以说&#xff0c;漏测的问题是测试管理者最头痛的问题。因为出现漏测&#xff0c;一来给客户…

总结是学习最好的方式(转)

总结是学习最好的方式 最近一直想总结来华为公司这3个多月自己有什么收获&#xff0c;但又想不明白自己收获了什么&#xff1f;说技术吧&#xff0c;也谈不上有多大的提高&#xff1b;说人际交流&#xff0c;也许还有些退步&#xff1b;说薪资存款吧&#xff0c;哎不谈了。想着…

【转载】JUnit各个注解的含义

转自&#xff1a;https://blog.csdn.net/weixin_38500014/article/details/84393775

silverlight、wpf中 dispatcher和timer区别

相同点&#xff1a;都是定时执行任务的计时器&#xff0c;都可以使用。 不同点&#xff1a;Timer运行在非UI 线程&#xff0c;如果Timer需要更新UI的时候&#xff0c;需要调用 Invoke或者 BeginInvoke DispatcherTimer运行在UI 线程&#xff0c;处理的 Dispatcher 队列中的计时…

web开发基础

web开发:所谓web开发就是基于浏览器服务器的开发下面将web开发基础知识作个总结:1.http协议:是建立在TCP协议上的,基于请求响应的模型2.http请求:面试题:说说get与post的区别a.传递数据量:get只能传递1kb以下的数据,post可以传递大数据b.安全性:get请求,如果携带参数,参数会直接…

让ubuntu下的eclipse支持GBK编码

原创作品&#xff0c;允许转载&#xff0c;转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://leaze.blog.51cto.com/83088/195584今天&#xff0c;把windows下的工程导入到了Linux下eclipse中&#xff0c;由于以前的工程代码&#x…

Session,ViewState用法

Session,ViewState用法基本理论&#xff1a; session值是保存在服务器内存上,那么,可以肯定,大量的使用session将导致服务器负担加重. 而viewstate由于只是将数据存入到页面隐藏控件里,不再占用服务器资源,因此, 我们可以将一些需要服务器"记住"的变量和对象保存到vi…

【HTML】记录自己丢人过程:文本换行缩进都不会

问题描述&#xff1a; html文本想实现换行和缩进&#xff0c;最后气到摔鼠标 换行 实现代码&#xff1a; <br> 直接在文本后加个换行标签即可 缩进 实现代码&#xff1a; style"text-indent: 2em;" 注意&#xff1a;这个属性放到p标签中或者div标签中都…

CentOS5.6系统下mysql5安装

我的系统是CentOS5.6 建议大家完全安装&#xff0c;以免安装时缺少相关的编译器等等。 一、安装mysql&#xff08;mysql-5.1.50.tar.gz&#xff09; # tar zxf mysql-5.1.50.tar.gz # cd mysql-5.1.50 #./configure --prefix/usr/local/mysql --sysconfdir/etc --localstated…

CentOS 6.9/7通过yum安装指定版本的JDK/Maven

说明&#xff1a;通过yum好处其实很多&#xff0c;环境变量不用配置&#xff0c;配置文件放在大家都熟悉的地方&#xff0c;通过rpm -ql xxx可以知道全部文件的地方等等。 一、安装JDK&#xff08;Oracle JDK 1.8&#xff09; # wget --no-check-certificate --no-cookies --he…

2019牛客全国多校训练三 题解

A Gragh Games Unsolved. B Crazy Binary String 题解&#xff1a;水题&#xff0c;子序列只要统计0和1数量&#xff0c;取最小值然后乘2就是答案&#xff1b; 对于子串&#xff1a;先记录0和1 前缀和的差值&#xff0c;然后找差值相等的距离最远的两个位置即可&#xff1b; 参…

【硬件基础】有源蜂鸣器与无源蜂鸣器

辨别方法 外观&#xff1a; 无源蜂鸣器: 有源蜂鸣器&#xff1a; 注&#xff1a;可以看到底部有绿色电路板的是无源蜂鸣器&#xff0c;底部是黑胶的为有源蜂鸣器 万用表电阻档检测 无源蜂鸣器&#xff1a;发出咔、咔声的且电阻只有8Ω&#xff08;或16Ω&#xff09;。 有源…

hdu 1272 小希的迷宫

Problem Description上次Gardon的迷宫城堡小希玩了很久&#xff08;见Problem B&#xff09;&#xff0c;现在她也想设计一个迷宫让Gardon来走。但是她设计迷宫的思路不一样&#xff0c;首先她认为所有的通道都应该是双向连通的&#xff0c;就是说如果有一个通道连通了房间A和B…

技术还是商业重要

在中国IT业创业听得最多的就是&#xff0c;技术不重要&#xff0c;商业和关系才是最重要的。 到了硅谷之后&#xff0c;发现技术气氛十分浓&#xff0c;甚至有朋友说大陆创业比较容易是因为硅谷与之相比&#xff0c;硅谷太注重技术了。 可是慢慢发现其实在硅谷&#xff0c;商业…

bzoj1036: [ZJOI2008]树的统计Count 树链剖分

一棵树上有n个节点&#xff0c;编号分别为1到n&#xff0c;每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作&#xff1a; I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的…

cocos lua 加密方案

cocos2d使用的是luajit&#xff0c;lua原生编译出来的bytecode和luajit是不兼容的&#xff0c;所以直接用luac法编译出来的bytecode脚本无法在cocos2d中使用。 目前所指的解决方案有2个&#xff1a; A.luajit加密&#xff1a; 1、官网下载luajit&#xff08;http://luajit.org/…

VS2010创建ATL类时需要手动填写ProgID

在新建ATL类的时候VS2010默认是不填写ProgID的&#xff1a; 所以默认创建的类生成的rgs文件中只有NoRemove CLSID这一栏&#xff0c;导致在JS中使用new ActivexObject(“LibName.ClassName”)失败。如果想用ActivexObject创建类的话就必须填写ProgID。转载于:https://www.cnblo…

【官网搭建】在网站首页底部添加备案号链接至工信部首页及版权所有。

在网站首页底部添加备案号链接至工信部首页及版权所有。&#xff08;工信部链接&#xff1a;http://beian.miit.gov.cn或http://www.beian.miit.gov.cn&#xff09; 在搭建网址的时候你是否受到过这种邮件&#xff1f; 下面提供一个代码模板 <div class"foot_bot&quo…

如何在linux下解压缩rar格式的文件压缩包

前言&#xff1a;没有特殊原因&#xff0c;文档如果要传到linux上&#xff0c;一定要打成*.zip格式&#xff0c; 这样方便解压&#xff0c;一般来说没有理由要用rar.关于 linux上unzip命令有空细讲&#xff0c; 本节讲下&#xff0c;如何让linux支持解压缩rar文件 一 、系统环境…

appium+python自动化45-夜神模拟器连不上(adb server version (36) doesn't match this client (39); killing...)...

前言 最新下了个最新版的夜神模拟器&#xff0c;然后adb devices发现连不上模拟器了&#xff0c;报adb server version (36) doesnt match this client (39); killing... 从报错信息看是adb版本不匹配导致的&#xff0c;接下来讲如何解决这个问题 环境&#xff1a; 夜神模拟器 …

Android.mk文件语法规范

序言&#xff1a; ------------- 此文档旨在描述Android.mk文件的语法&#xff0c;Android.mk文件为Android NDK(原生开发&#xff09;描述了你C/C源文件。为了明白下面的内容&#xff0c;你必须已经阅读了docs/OVERVIEW.TXT的内容&#xff0c;它解释了Android.mk文件扮演的角色…

【硬件基础】制作直流电源

要求&#xff08;其实就是个课设&#xff09;&#xff1a; 利用二极管的基本特性、三极管的基本特性、稳压电源等知识&#xff0c;设计相 应的模拟电路&#xff0c;设计制作放大倍数可变的直流放大器。 任务要求&#xff1a; &#xff08;1&#xff09;用集成芯片制作一个 0~1…

RanceQuest2_从委托到Lambda_会用(递归数学函数)

二连发 使用Lambda表达式编写递归函数 ——摘自老赵点滴 - 追求编程之美。 todo用手敲30遍&#xff0c;搞定——泛型委托&#xff0c;Lambda表达式&#xff0c;简单的数学递归。 遗憾的是&#xff0c;原本希望更进一步做出一个通用的递归方法表达式出来&#xff0c;受所学所限&…

[转载].sscanf的用法

原作者不详。 名称: sscanf() - 从一个字符串中读进与指定格式相符的数据. 函数原型: Int sscanf( string str, string fmt, mixed var1, mixed var2 ... ); int scanf( const char *format [,argument]... ); 说明&#xff1a; sscanf与scanf类似&#xff0c;都是用于输入的&a…

As与强制类型转换的区别以及Is运算符的使用

前言&#xff1a; 开发人员经常需要将一个对象从一个类型转换成其他类型。 在c#中&#xff0c;类型转换按照转换方式分类分为了隐式转换和显式转换&#xff0c;按对象分类又分为了值类型转换和引用类型转换  CLR(参考&#xff1a;http://baike.baidu.com/view/605055.htm)允许…