关注“Java后端技术全栈”
回复“000”获取大量电子书
final、finally、finalize 有什么区别?
这是一个初级面试题,在中高级面试中也会出现。
final关键字
初级回答
final
,是修饰符关键字。
- 修饰类,表示该类不能在被继承。
- 修饰方法,表示该方法不能被子类重写。
- 修饰变量,表示该变量是常量,不能被修改。
中高级回答
- 如果一个类被声明为
final
,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为abstract
的,又被声明为final
的。 - 将变量或方法声明为
final
,可以保证它们在使用中不被改变。被声明为 final 的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final
的方法也同样只能使用,不能重写。
另外,在早期的 Java 实现版本中,会将
final
方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升(现在的 Java 版本已经不需要使用final
方法进行这些优化了)。类中所有的private
方法都隐式地指定为final
。
String 、Integer、Long等类都是final修饰的类。其保存值的属性也是final修饰的。
final修饰基本数据类型和修饰引用数据类型。
如果final修饰的是一个基本数据类型的数据,一旦赋值后就不能再次更改 ,而对于引用类型变量而言,它仅仅保存的是一个引用,final只保证这个引用类型变量所引用的地址不会发生改变,即一直引用这个对象,但这个对象属性是可以改变的。
finally关键字
初级回答
通常放在try…catch…的后面构造总是执行代码块,这就意味着程序无论正常执行还是发生异常,可以将释放外部资源的代码写在finally块中。
使用方式:
try{
//业务代码
}catch(){
//异常处理
}finally{
//释放资源等
}
try{
//业务代码
}finally{
//释放资源等
}
高级回答
在异常处理时提供 finally
块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch
子句就会执行,然后控制就会进入 finally
块(如果有的话)。
通常在处理一些资源的时候,会使用finally来关闭相关资源。比如说:操作文件,使用ReentrantLock
锁,分布式锁等。
在以下 4 种特殊情况下,finally块不会被执行:
- 在
finally
语句块中发生了异常。 - 在前面的代码中用了
System.exit()
退出程序。 - 程序所在的线程死亡。
- 关闭 CPU 。
finalize方法
finalize
,是方法名。
初中级级回答
Object类中定义的方法,Java中允许使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在销毁对象时调用的,通过重写finalize()方法可以整理系统资源或者执行其他清理工作。
听到这里就知道这面试题答案是背的
高级回答
Java 允许使用 #finalize()
方法,在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。
- 它是在 Object 类中定义的,因此所有的类都继承了它。
- 子类覆盖
finalize()
方法,以整理系统资源或者执行其他清理工作。 #finalize()
方法,是在垃圾收集器删除对象之前对这个对象调用的。
这个方法在工作中最好别用,如果用了可能会带来意想不到的难题,一般情况下,我们在业务中不会自己实现这个方法 。
大致过程:
- 垃圾回收器发现该对象实现了finalize()方法。因为会把它添加到
java.lang.ref.Finalizer.ReferenceQueue
队列中。 Finalizer
线程会处理这个队列,将里面的对象逐个弹出,并调用它们的finalize()方法。- finalize()方法调用完后,
Finalizer
线程会将引用从Finalizer
类中去掉,因此在下一轮GC
中,这些对象就可以被回收了。 Finalizer
线程会和我们的主线程进行竞争,不过由于它的优先级较低,获取到的CPU时间较少,因此它永远也赶不上主线程的步伐。- 程序消耗了所有的可用资源,最后抛出
OutOfMemoryError
异常。