admin管理员组文章数量:1122879
谈谈final, finally, finalize
final, finally和finalize看起来很相似, 但是工作内容完全不相同.
final关键字
final
可以用来修饰在类, 方法和变量上:
- 修饰在类上: 该类不可以被集成, 失去扩展性;
- 修饰在方法上: 该方法不可被重写(Override);
- 修饰在变量上: 变量的值无法被修改;
修饰类
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 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/biancheng/1707373918a724974.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论