final
修饰类:该类不可被继承扩展
修饰方法:该方法不可被重写
修饰变量:当变量赋值后不可被修改
final修饰的变量,如果值是"对象引用",那么不可改变的是这个引用,而不是引用指向的地址中存的值,比如数组
final int[] a = [1,2,3];
int[] b = [2,3,4];
//这是会报错的,a的值是数组的地址,不能被修改
a = b;
//这是可以的,因为并没有改变a值(也就是数组的引用地址)
a[0] = 32;
immutable状态不可变模式
指对象一旦初始化建立之后,其属性均不可变,常用于多线程保障线程安全
它基于final建立,String类就是典型的immutable模式
1.用final修饰类名,保障其不可继承
2.用final修饰属性,保障其赋值后不可被更改
3.去除setter方法
4.getter方法中返回新建对象,防止通过对象引用更改其数据
5.构造方法中给类属性赋值时,构建新对象赋值,防止通过对象引用更改数据
public final class Test{
private final char[] value;
public Test(char[] v){
this.value = Arrays.copy(v,v.length);
}
public char[] getter(){
return Arrays.copy(v,v.length);
}
}
String s = “str” 与 String s = new String(“str”) 的区别
前者:对象创建前,去常量池中寻找,如果有,则直接将s引用指向该现存的对象,如果没有,则在常量池中创建。所以 String a = “111” 和 String b = “111” 引用指向的地址是相同的,即 a == b 返回true
后者:在堆内存中创建新对象,所以 String a = new String(“111”) 和 String b = new String(“111”)引用地址不同,即 a==b返回false
String类设计成不可变的目的
安全:从多线程并发角度考虑,如果设置为可变的,有可能多个线程操作同一对象而不自知。
高效:如果想创建的值是相同的,常量池中有则沿用,没有才会进行创建,这样节省了空间和效率。
String类的缺点
如果创建过多,会在常量池产生很多无用的垃圾。
finalize
它的设计目的是保证对象在被垃圾收集前完成特定资源的回收
在JVM在执行GC垃圾回收时,若类对象重写了finalize方法,则将其移交给FinalizerThread处理,该对象被添加到FinalizerThread的执行队列中。GC是自动回收的,所以无法保证对象中finalize方法的及时性;并且,其置于队列中,存在死锁的可能性。JAVA9中建议以Cleaner类代替finalize。
注意: 无论是finalize还是Cleaner,他们都不是资源回收这项工作的主要承担者,他们只是最后一道防线。