基本回答
final:
可以修饰变量,方法,类。 修饰类的时候,表示该类不允许被继承; 修饰方法的时候;表示该方法不允许被overload; 修饰变量的时候,表示该变量是不可变的(很重要),在进行多线程的时候,在进行函数式编程的时候,前者希望能让变量成为不可变的,后者会在编译期强制让变量声明为final的。
finally
这是Java中的一个语法糖,表明了一段无论如何都希望执行的代码,(会在return之前执行)除了System.exit(0),或者死循环出现的话,finally中的代码也确实会保证它的执行;
finalize
这是Object中的一个方法,它的作用是,调用之后希望能够提醒垃圾收集器回收垃圾。不过实际上,这个方法的效果是很差的,很可能带来反效果。
扩展
final
final和函数式编程一起通常会涉及闭包的概念:
final int a; int method(){ return a; }
这就是一个闭包,如果a不是final的,method()方法也会成为一个不可控的方法;这样的思想也可以应用在多线程下,假如多线程中的变量不是final的,也给多线程带来了更多的不可控性质,也省去了一下防御性拷贝的必要(CopyOnWriteArrayList为了避免出现ConcurrentModificationException,实际上就采用了防御性拷贝的方案)
在Java基本类库中,声明了final的类和方法,避免了API使用者更改基础功能,某种程度上保证了平台的安全性;
final在某种程度上并不能保证immutable,在使用的是引用数据类型时,不可变的只是引用,而引用中如果还包含着引用,它是不能保证的
final List list = new ArrayList();
list.add(123);
彻底的不可变,list.add(123)这样的程序也是不被允许的,而Java中final声明的List是允许的。这个时候应该使用一个不可变的List。
Immutable 在很多场景是非常棒的选择,某种意义上说,Java 语言目前并没有原生的不可变支持,如果要实现 immutable 的类,我们需要做到:
- 将 class 自身声明为 final,这样别人就不能扩展来绕过限制了。
- 将所有成员变量定义为 private 和 final,并且不要实现 setter 方法。
- 通常构造对象时,成员变量使用深度拷贝来初始化,而不是直接赋值,这是一种防御措施,因为你无法确定输入对象不被其他人修改。
- 如果确实需要实现 getter 方法,或者其他可能会返回内部状态的方法,使用 copy-on-write 原则,创建私有的 copy。
final可以和volatile比较一下:
- final表示不可变,针对多线程来说,保证大家使用的是同一个东西;
- volatile表示可见,针对多线程来说,保证假如自己发生变化了,别人能看到;
finalize
finalize的效果很烂,但是要说清楚多烂,就需要清楚垃圾回收机制和强引用,软引用,弱引用,幻想引用引用知识。 除了finalize,Java还提供了Cleaner机制。