Java中的final、finally、finalize
一、前言
算是个在Java初级的面试中经常会被问到的一个点吧,不过现在估计没有人问了。其实三个词在Java中并没有什么相关性,完全是风马牛不相及,纯粹是字面上的相似。
二、final
final是Java中的关键字,简单从字面意思上理解为:不可变的。final可以用来修饰Java中的类、方法、变量。
1.final类
final来修饰类表示类不可变时,表明了该类不能被继承。当我们希望保持一个类的实现不被继承改变时,可以用final来进行修饰。同时,隐含的,final修饰类中的方法默认为final(不需要再显示声明)。实际使用中我们很少会去写一个final的类,最经常用到的莫过于JDK提供的String类就是final类。
2.final方法
final修饰方法表示方法不可变时,表明了该方法不能被覆盖重写。我们通常把一个类声明为final来保证子类不会通过重写来改变父类的行为和实现。
当然在早期的JDK版本中,把方法声明为final还有一层考量:效率。final的方法在编译时会进行一定的优化处理来提高效率。但现在JVM的发展已经完全不需要再因为这个原因来写一个final方法了。
3.final变量
final修饰变量表示变量不可变时,表明了该变量不能被修改。对于Java中的基本类型来说,final修饰的变量在被初始化赋值后就不能再改变。但对于引用类型来说,final修饰是指的该引用不能再被改变,即:引用指向的内存地址不能被修改。但引用所实际指向的对象内容是可以被改变的。
image.png被final修饰的成员变量必须显示的初始化赋值,一种是在声明时直接初始化赋值,一种是在所属类的构造函数中赋值。
image.png
当方法参数被final修饰时,与普通变量被修饰类似,表明了该参数只能被读取使用,不能修改。
三、finally
finally也是Java中的关键字,用在异常机制处理中修饰代码块,从字面可以理解为最终,即finally块中的代码最终会被执行。
细化理解:
- finally一定是和try-cath配合使用。
- finally块中的代码无论是正常流程还是抛出异常都会被执行
- 通常我们使用finally保证获得的资源,比如:IO流、数据库连接等在异常情况下都能得到释放。
finally代码最终一定会被执行是在执行try-catch-finally代码时一定会被执行,如果在此之前调用就已经返回则不会触发执行。另外如果程序异常退出或者System.exit()显示退出时也不会得到执行。
finally对return的影响:因为finally最终并且是最后会被执行,导致甚至能修改已经return的返回值。
四、finalize
finalize是指Java中的finalize方法,该方法由Object类默认提供,因此所有的类都含有该方法。finalize方法设计出来用于在JVM垃圾回收gc时释放相关资源,但是finalize方法的调用执行有诸多限制,比如:执行线程优先级低,方法仅能调用一次等。所以可以看做是老版本JVM的一个遗物,基本上很少使用。
五、总结
不要被字面的相像所迷惑,稍微一对比分析就可以发现三者完全是挨不上边。
题外
说道final修饰的不可变类,可以与多线程并发的不可变类Immutable Class进行一个比较。
final修饰的不可变是从Java的继承机制上的一种限制
多线程并发中的不可变类是指该类的对象为不可变对象,一旦被创建,对象的相关属性-值都不能再被改变。通用用于并发操作中保证数据的安全。
例如:String类同时也是Immutable Class,所有的String对象在创建后都不能被改变。而我们平常代码中对String对象的修改实际并没有修改原对象,而是生成了一个新的对象并返回。如:substring方法或者+做字符串连接。因为每次做字符串连接都会生成新的对象,所以通常开发中要极力避免在循环中使用字符串连接,并使用StringBuilder来代替。
image.png