1. final
在java中,final可以用来修饰类,方法和变量(成员变量或局部变量)。final修饰的class表示类不可以继承扩展;修饰的方法表示方法不可以被重写(override);修饰的变量表示变量是不可以修改的。
问: 在java中,String被设计成final类,那为什么平时使用时,String的值可以被改变呢?
字符串常量池是java堆内存中一个特殊的存储区域,当我们建立一个String对象时,假设常量池不存在该字符串,则创建一个,若存在则直接引用已经存在的字符串。当我们对String对象值改变的时候,例如 String a="A"; a="B" 。a是String对象的一个引用(我们这里所说的String对象其实是指字符串常量),当a=“B”执行时,并不是原本String对象("A")发生改变,而是创建一个新的对象("B"),令a引用它。
问:为什么String 会设计成final?
翻开JDK源码,java.lang.String类起手前三行,是这样写的:
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
/** String本质是个char数组. 而且用final关键字修饰.*/
private final char value[];
...
...
}
首先String类是用final关键字修饰,这说明String不可继承。再看下面,String类的主力成员字段value是个char[ ]数组,而且是用final修饰的。final修饰的字段创建以后就不可改变。
value是不可变,也只是value这个引用地址不可变。挡不住Array数组是可变的事实。
这样设计的好处:(1)安全,比如线程安全;(2)支持常量池
参考: https://blog.csdn.net/u013905744/article/details/52414111
三者的区别:
(1)字符修改上的区别(主要)
String:不可变字符串;
StringBuffer:可变字符串、效率低、线程安全;
StringBuilder:可变字符序列、效率高、线程不安全;
(2)初始化上的区别,String可以空赋值,后者不行,报错
小结:(1)如果要操作少量的数据用 String;
(2)多线程操作字符串缓冲区下操作大量数据 StringBuffer;
(3)单线程操作字符串缓冲区下操作大量数据 StringBuilder(推荐使用)。
参考:https://www.cnblogs.com/su-feng/p/6659064.html
2. finally
finally作为异常处理的一部分,它只能用在try/catch语句中,并且附带一个语句块,表示这段语句最终一定会被执行(不管有没有抛出异常),经常被用在需要释放资源的情况下。
3. finalize(不推荐使用)
finalize()是在java.lang.Object里定义的,也就是说每一个对象都有这么个方法。这个方法在gc启动,该对象被回收的时候被调用。其实gc可以回收大部分的对象(凡是new出来的对象,gc都能搞定,一般情况下我们又不会用new以外的方式去创建对象),所以一般是不需要程序员去实现finalize的。
特殊情况下,需要程序员实现finalize,当对象被回收的时候释放一些资源,比如:一个socket链接,在对象初始化时创建,整个生命周期内有效,那么就需要实现finalize,关闭这个链接。
使用finalize还需要注意一个事,调用super.finalize();
一个对象的finalize()方法只会被调用一次,而且finalize()被调用不意味着gc会立即回收该对象,所以有可能调用finalize()后,该对象又不需要被回收了,然后到了真正要被回收的时候,因为前面调用过一次,所以不会调用finalize(),产生问题。 所以,推荐不要使用finalize()方法,它跟析构函数不一样。
finalize不推荐使用,在JAVA 9 中,Object.finalize() 被标记成deprecated!如果没有特别的原因,不要实现finalize()方法,也不用指望利用它来进行资源回收!java.lang.ref.Cleaner和java.lang.ref.PhantomReference提供更灵活和有效的方式,在对象无法再访问时释放资源。