前言
看见即降服,这句话说的是一件事物,只要你看得到,你就能得到。
对我来说记录就是看见。
面试题不只是为了面试,更是为了帮助我们更深入地理解我们已知的知识。
问题分析
当听到这个问题的时候,有种上学时候那种应试考试的感觉,不知道在坐的各位有没有。因为final,finally,finalize这三个根本没有任何联系,只是长得像而已,仅此而已。这个问题跟重写和重载的有什么区别一样,看起来像是考官为了凑题数才出的题。但是既然有人提出这个问题,那出题人肯定有他自己的出发点,我猜是为了考察我们对这些关键字意思的理解程度。那么接下来我们看一下这三个关键字都是什么意思,有什么作用。
final
首先我们知道,final
的中文意思是最终,它在java语言中是一个修饰符,就像pulbic
,private
等修饰符一样,ok,我们现在知道了final
的作用是修饰。既然是修饰符,那它能修饰什么呢?答案是非抽象类,非抽象方法,变量。下面我们分开来讨论下。
修饰非抽象类
-
有什么作用/结果/效果
答:作用就是这个类不能被继承了,因为不能被继承,所以它的所有方法默认都是
final
(因为被final修饰的方法不可以被子类重写)。 -
什么时候用
答:当你设计一个类不需要子类或者不想被别人继承扩展的时候,加上
final
修饰就行了。例如String
(关于String
的final
设计可以看一下为什么String要设计为final,不要问我为什么每篇文章都要用别人文章的引用,问就是我要站在巨人的肩膀上)。
修饰非抽象方法
这个主要是为了不让其子类对重写该方法。还有一个作用是效率(这个作用可以看下文章底部的参考链接)。
修饰变量
final
修饰的变量分两种:
- 修饰基本变量:例如
final int a = 1;
;首先要明白基本变量在内存中的存放位置是什么(这个内存的东西可以学习一下JVM那本经典的书),好啦,答案是基本变量存放的位置方法栈。那么final
修饰基本变量的时候对基本变量有什么作用呢?答案是,这个基本变量a
所指的内存地址(也就是1
所在的内存地址)不能再被修改了。 - 修饰引用变量:例如
final Person p = new Person()
;首先我们需要知道引用变量在内存中存放的位置是堆。同上,这个final
的修饰作用是p
所指的内存地址不能再被修改了,但是对于引用变量来说,只是内存地址不可以被改变,内存地址中的内容可以改变。
你要问我为什么基本变量的内容不可以变?这个问题。。。好吧,我们如果要改变基本变量a
的内容,我们是不是要这么写a = 2;
?那首先不说ide会编译不过,即使编译过,我们想一下,java中整数-127-128是默认被加载到常量池里的,那么a = 2;
就会导致引用a
的指向从1
的内存地址变为2
的内存地址,这个是不是就和被
final修饰的变量,变量引用所指的内存地址不可被修改
这句话矛盾了?
总结引用下文末文章的一句话:
final修饰变量的本质: final修饰的变量会指向一块固定的内存, 这块内存中的值不能改变.
对于final
这个关键字的知识点还有一些深层次的东西,大家可以详细查看文末的链接!
finally
finally
这个关键字是和try...catch
配合使用,它的作用:
-
处理完异常后对资源进行释放
-
为什么有上面
作用1
的效果呢?是因为一般情况下finally
的代码块都会执行,非一般情况可以点击第三条的链接详细查看。
finalize
额,首先finalize
是一个方法,应该是finalize()
。它是Object
类中的一个方法。
这个方法的定义是这么说的:
Called by the garbage collector on an object when garbage collection determines that there are no more references to the object.
翻译如下:当我们内存堆中的某个对象没有被任何其引用时并且垃圾回收器gc准备回收该对象的时候,finalize()
方法将被调用。
那么对于finalize()
方法的调用问题可以看一下SO社区(StackOverflow是一个非常好的网站,作为程序员开发的我们不应该忽视这个网站)java中的finalize()方法什么时候会调用?。
这个OP(Origin Post)的问题是:
我创建了一个类,并在finalize()
方法里面执行了文件的写入操作(意思是他想通过文件是否有写入东西来判断finalize()
是否被调用),但是这个方法从来都没有被执行。
Vote Up最多的并被接受的一个回答是:
大概意思是:请阅读javadoc,finalize()
方法可能在程序的一生中都不会被调用,并且垃圾回收器也不保证在某个特定时间会执行。所以除非你有特定需求否则不要依赖finalize()
。(好吧,我也不清楚什么才算特定需求,我在开发过程中也没用过这个方法,如果在坐各位谁对该方法有经验,欢迎评论区指出!)