前言
这篇速读文章来自面试的常客final、finally、finalize。说实话不大很理解为啥很多面试官喜欢把这三者放在一起。这完全不相干啊!不过既来之则安之吧。
今天让我们聊一聊final、finally、finalize各自的场景。
正题
引子
小A:MDove,我最近发现很多文章会把final、finally、finalize放在一起比较。恕我愚钝,我实在不知道它们有什么关系。
MDove:它们的关系你竟然看不出来?这不就是:这三者就是卡巴斯基、巴基斯坦和小丑巴基的关系,有个基巴关系!
小A:啊?……
final
MDove:对于我们来说final是很基础的关键字。final可以用来修饰类、方法、变量。
1、final修饰的class,代表不可以继承扩展。2、final的方法也是不可以重写的。3、final修饰的变量是不可以修改的。MDove:咱们重点提一提第3点,这里所谓的不可修改对于基本类型来来,的确是不可以修改。而对于引用类型来说,只能说不能重新赋值。也就是不能改变引用地址。但是作为引用类型,它内部所包含的内容如果不是final则可以随意修改咯,就像:
final List<string> arryList = new ArrayList<>();
arryList.add("AAA");
arryList.add("BBB");
List<string> unmodifiableArrayList = List.of("AAA", "BBB");
unmodifiableArrayList.add("CCC");
/<string>/<string>
MDove
MDove:我们都知道final声明的变量需要显示的给它赋初始值的。这里考考你,如果不想直接给它赋值,那应该怎么做?
小A:我猜…需要在构造方法里边吧?
MDove:没错的确是这样:
fianl int num;
final int num2 = 666;
public Test(){
num = 666;
}
MDove:前面的文章,我们有提到其实这俩种写法,对于编译的class文件是等价的。
MDove:关于final,还有个有趣的地方。在很多文章中,会提到在特定场景下final能够提高性能。比如:利用final可能有助于JVM将方法进行内联,可以改善编译器进行条件编译的能力等等。说实话这种假设完全没有考虑的必要。
finally
MDove:接下来让我们来聊一聊finally。提到finally,那么try-catch就逃不掉了。finally 则是Java保证重点代码一定要被执行的一种机制。最常用的地方:通过try-catch-finally来进行类似资源释放、保证解锁等动作。比如:
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream(new File("test"));
System.out.println(inputStream.read());
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
}
MDove:这里提一点,try-finally也是可以的。不过这里个人不建议省略掉catch。因为前一段时间我们就踩到了这个坑。我们项目里捕获的异常,一般都会在catch里通过Error的CallBack传出去,打Log。那次我们在追一个Bug的时候,发现竟然什么Log都没有。后来才发现,出Bug的地方,try异常后没有做任何处理直接finally,导致没有办法看到Log日志,浪费了很多时间。
try (FileInputStream inputStream = new FileInputStream(new File("test"))) {
System.out.println(inputStream.read());
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
这二者的写法是等价的。当然这只是一种语法糖~
MDove:当然有些丧心病狂的题目,会问你什么情况下finally不执行。这种情况就不执行了:
try {
System.exit(1);
} finally{
System.out.println(“程序都死了,我还执行个毛线~”);
}
MDove:可以看出,能导致程序停止的操作,finally都没办法执行了。说实话这真的没有啥意义…
MDove:最后我们来聊一聊finalize。
finalize
MDove
MDove:关于finalize说白了,它设计之初的作用就是:在CG要回收某个对象时,让这个对象有底气的大喊一声:“报告,我还能再抢救一下!”。但是也正是因为如此,JVM要对它进行额外处理。finalize也就成为了CG回收的阻碍者,也就会导致这个对象经过多个垃圾收集周期才能被回收。
MDove:因为我自己对finalize了解也不是很深,所以关于finalize的内容就暂时让我们止步于此。如果你还是感兴趣,可以搜一搜相关的分析文章。
MDove:不知道一路捋到这,你是不是多少对这三者有了一些了解。实话实说,他们三者了解了解就完OJBK了,知道它们设计的初衷,了解它们的用法。可以灵活多变的应用到业务中就哦了。过分的追求一些“奇技淫巧”,反而失去了设计本身的意义。
小A:真是学无止境,我觉得我好想选错了行业。