final, finally和finalize看起来很相似, 但是工作内容完全不相同.

final关键字

final可以用来修饰在类, 方法和变量上:

  1. 修饰在类上: 该类不可以被集成, 失去扩展性;
  2. 修饰在方法上: 该方法不可被重写(Override);
  3. 修饰在变量上: 变量的值无法被修改;

修饰类

Java语言的设计人员也在设计一些非常基础的类的时候, 也会将这些类使用final来修饰, 我们可以在java.lang包下面发现相当一部分类都是如此, 比如String:

public final class Stringimplements java.io.Serializable, Comparable<String>, CharSequence {// other code
}

同样在很多的第三方类库中也是这样, 这样可以有效避免API使用者更改基础功能, 也是保证平台安全的必要手段.

修饰方法

在实际开发的过程中, 我们经常使用final关键字来明确表明我们代码的语义和逻辑结构, 比如在考虑模板方法设计模式的实现过程中, 通常会将顶层模板父类中的模板方法设置为final, 这样实现子类在继承父类之后, 就无法重写一个模板的执行顺序, 从而保证了程序安全.

定义一个玩电脑游戏的模板类如下:

package com.ee2j.spring.design;/*** 玩电脑游戏*/
public abstract class PcGame {public final void playGameTemplate() {// 打开电脑openPc();// 玩具体的游戏playGame();// 关闭电脑if (needClose()) {closePc();}}private void openPc() {System.out.println("打开电脑!");}private void closePc() {System.out.println("关闭电脑!");}protected abstract void playGame();protected boolean needClose() {return Boolean.TRUE;}
}

上述代码中, playGameTemplate()final修饰之后, 子类继承Game之后是无法对这个核心的流程做直接修改的, 只能通过该套模板设计者留下的钩子方法needClose()有限地调整部分流程的执行.

修饰变量

使用final修饰参数或者变量, 也可以清楚地避免意外赋值导致的编程错误, 比如在实际开发过程中, 我们会借助常量(Constant)来进行多个方法之间的通信, 常量的意义就是保证该变量在任何场景下的表达都始终如一, 这就需要借助final的力量了, 比如定义一个标识成功的常量:

public final static String SUCCESS = "success";

在应用开发过程中, 如果尝试对上述代码中的SUCCESS变量做任何重新赋值的操作, 都会出现编译错误, 从而无法改变这个变量当前的值, 从而保证了调用该变量的表现一致, 这样团队中其他成员也无需在意该变量的具体值是什么.

再谈final

通过上述的例子, 我们可以看到final确实带来了某种程度上的不可变效果, 所以可以用于来保护只读数据, 在多线程编程中, 因为明确地不能再赋值final变量, 也可以省去一些额外的同步开销.

但是需要注意的是, final的效果并不是immutable, 比如如下代码:

public final static Double RANDOM = Math.random();

很明显, RANDOM看上去也很符合常量该有的样子, 但是如果在引用开发过程中调用这个"常量", 可能问题就会出的很大, 因为会发现, 每次调用RANDOM之后的结果并不是一样的 !

这是因为final其实约束的只是针对该变量的引用或者赋值, 也就是只能赋值一次, 不能重复赋值, 但是引用的对象本身内部变化, final是没办法管的, 这就要求我们在开发过程中避免为final变量复杂赋值, 务必让常量的值在运行期保持不变.

finally代码块

finally是Java保证重点代码一定要被执行的一种机制, 放在finally代码块中的代码一定会执行, 不管上面的代码执行结果如何(但是有一种特殊情景例外, 下文再论…).

所以我们在实际开发过程中, 一般是通过try-finally或者try-catch-finally形式来进行类似关闭JDBC连接或者Stream的close, 保证unlock等动作, 如下代码所示:

public void close() {FileInputStream fis = null;try {fis = new FileInputStream("xxx.xml");} catch (FileNotFoundException e) {// other code} finally {if (fis != null) {try {fis.close();} catch (IOException e) {// other code}}}
}

这样即使文件没找到, 抛出了异常终止了接下来的业务程序, 我们也可以正常的关闭流.

但是如果你现在选择的Java版本是Java 7以上, 那么更推荐Java 7开始提供的try-with-resource语句, 因为相信Java平台可以更好的处理异常情况, 同事编码量也可以小一些, 何乐而不为呢? 那么, 我可以将上述代码修改如下所示:

try (FileInputStream fis = new FileInputStream("xxx.xml")) {// other code} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}
}

很明显, 可以看到代码量的减少, 而且也没有显式编写关闭流的操作了, 那么流是真的没有关闭么, 其实并不是, 那是因为FileInputStream实现了AutoCloseable接口, 可以从该接口的文档注释中找到如下描述:

/* An object that may hold resources (such as file or socket handles)* until it is closed. The {@link #close()} method of an {@code AutoCloseable}* object is called automatically when exiting a {@code* try}-with-resources block for which the object has been declared in* the resource specification header. This construction ensures prompt* release, avoiding resource exhaustion exceptions and errors that* may otherwise occur....other comments*/

也就是说, 只要是实现了AutoCloseable并在try()中声明的对象, 当try-with-resource代码块执行完的时候,会自动调用close()方法, 所以该步骤是交给Java平台帮我们完成了.

再谈finally

上文说到, 放在finally代码块中的代码一定会执行, 但是会有一种异常情况, 各位看官且观如下代码:

try {System.exit(1);
} finally {System.out.println("come from finally");
}

该段代码的执行结果会是什么? 会输出"come from finally"语句么, 并不会! 因为System.exit(status)用于中断正在运行之中的Java虚拟机, 虚拟机都被干了, 剩下的是啥也无所谓了…当然这是一个极端情况, 正常不会出现这个情况.

finalize方法

finalize()是基础类java.lang.Object的一个方法, 它的作用是保证对象在被垃圾回收之前完成特定资源的回收, 算是个对象生命周期结束之前的"遗言"吧. 但是这个方法已经不推荐使用, 在Java 9中甚至已经被@Deprecated.

为什么这个方法这么不受待见呢 ?

是因为finalize()被设计成在对象被垃圾收集前调用, 这样我们无法保证finalize()什么时候执行, 而且它的执行结果是否能够符合我们的预期.

并且如果finalize()如果不是一个empty的方法, JVM需要对这个对象进行额外的处理, 这样就从本质上成为了快速回收的阻碍, 可能会导致这个对象在多个垃圾收集周期才能被回收, 这样可能会造成等待垃圾收集的对象的堆积, 也是很有可能会造成Out Of Memory的error的 !

谈谈final, finally, finalize相关推荐

  1. 谈谈 final、finally、 finalize 有什么不同?

    谈谈 final.finally. finalize 有什么不同? final 可以用来修饰类.方法.变量,分别有不同的意义,final 修饰的 class 代表不可以继承扩展,final 的变量是不 ...

  2. java基础知识1---面向对象及final,finally,finalize区别

    1.面向对象(OOP)的特征 •抽象 :就是把现实世界中的某一方面提取出来,用程序代码表示,抽象出来的一般叫做类或接口. 抽象包括两个方面,一个数据抽象,另一个是过程抽象. 过程抽象 :表示功能的操作 ...

  3. 关键字回顾(final/finally/finalize()、Synchronized、volatile、static)

    1. final, finally, finalize的区别 final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承. finally是异常处理语句结构的一部分,表示总是执行 ...

  4. final finally finalize三者有什么区别

    final   finally   finalize三者有什么区别 : (1)final: a) 一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承.因此一个类不能既被声明为a ...

  5. final是什么?作用?以及final finally finalize区别?

    final是什么? final: 最终的意思,修饰的东西不可改变.可以用于修饰类.方法和变量. final 有什么用? 被final修饰的类不可以被继承 被final修饰的方法不可以被重写 被fina ...

  6. final finally finalize()区别

    final finally finalize()区别 final 表示最终的.不可改变的.用于修饰类.方法和变量. finally 异常处理的一部分,它只能用在try/catch语句中,表示希望fin ...

  7. Android源码中final关键字的用法及final,finally,finalize的区别

    Android开发的学习流程 final,finally,finalize的区别 Android的发展越来越快,Android开发人员越来越多,当两种情况碰撞,在诸多开发者中跟紧Android步伐脱颖 ...

  8. final finally finalize 的区别

    1.final final修饰类,说明这个类不能被继承,是以个顶级类. final修饰变量,说明这个变量是常量. final修饰方法,表示这个方法不能被重写,不过可以冲在final方法. 比如有个基类 ...

  9. final,finally,finalize的区别

    1.final 修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承.因此一个类不能既被声明为 abstract的,又被声明为final的.将变量或方法声明为 ...

最新文章

  1. 十六届全国大学生智能车竞赛线上比赛的队伍看过来,你们需要的图片都在这儿
  2. 关于Rocchio算法和向量空间模型反馈
  3. a singleton implemention
  4. 平衡二叉树(AVL Tree)(左旋、右旋)
  5. 三菱d700变频器接线图_图解PLC与变频器通讯接线
  6. 9 计算机组成原理第五章 中央处理器 指令流水线
  7. linux CentOS7 最小化安装环境静默安装Oracle11GR2数据库(安装操作系统环境_01)
  8. Python编程基础15:异常
  9. [运维笔记] - (命令).Windows server常用网络相关命令
  10. 2015百度之星资格赛.1004放盘子(数学推导)
  11. 弱口令扫描工具mysql ftp_超级弱口令检查工具
  12. excel 合并单元格筛选
  13. “新元宇宙”奇科幻小说原创作品系列连载《地球人奇游天球记》第三回零点惊魂
  14. html怎么移动按钮位置,CSS Nav按钮向左下方移动(CSS Nav buttons move bottom left)
  15. 计算机专业高级工程师考哪些专业,高级工程师职称考试项目有哪些
  16. iTunes Connect 人员如何使用testflight安装测试版ios应用
  17. DEBUG系列二:ConfigureDebuggerLayer_SAP刘梦_新浪博客
  18. java.lang.IllegalArgumentException: DrawerLayout must be measured with MeasureSpec.EXACTLY
  19. End-to-End(端到端)的理解
  20. 驱动级键盘记录器与安全密码框(能获取QQ密码)

热门文章

  1. 软工视频学习笔记——02
  2. Python爬取链家成都小区信息
  3. 公众号下面显示一排服务器,公众号服务器如何调试
  4. 如何有效利用大数据?
  5. win11系统没有本地用户和组?
  6. 中概股最牛财报!直播这么火为何却只有陌陌赚了大钱?
  7. 临床执业助理医师(综合练习)题库【6】
  8. 用Vue Node从零开始实现拼多多前后端商城项目 — 记录踩坑之旅(上篇)
  9. 微信小程序获取appId
  10. 那个点燃了火堆,并且拥有200多个笔名的男人