关于不可变对象,在《JAVA并发编程实战》中有个例子一直不能理解,如下图
为什么这个是不可变对象?换个问法,为什么书中提到
博主想了一晚上也没搞明白这句话的含义,直到博主又想起了被java值传递概念支配的恐惧,便写了下面的几行小代码验证猜想:
//尝试构建不可变类
class Object2{
private final int[] myArray;
public Object2(int[] myArray) {
this.myArray = myArray;//此法不可以构建不可变对象,记住值传递,传递的是数组地址,数组变了,对象也变了
}
@Override
public String toString() {
return "Object2 [myArray=" + Arrays.toString(myArray) + "]";
}
}
class Object3{
private final int[] myArray;
public Object3(int[] myArray) {
this.myArray = Arrays.copyOf(myArray, myArray.length);//此法不可以构建不可变对象,记住值传递,传递的是数组地址,数组变了,对象也变了
}
@Override
public String toString() {
return "Object3 [myArray=" + Arrays.toString(myArray) + "]";
}
}
public class ValuePass {
public static void main(String[] args)throws Exception{
//尝试Object2不可变性的测试
int[] arr = new int[]{1,2};
Object2 obj2 = new Object2(arr);//传递的是数组的地址(堆地址)
System.out.println(obj2);
arr[0]= 2;//改了
System.out.println(obj2);//此处也会变化,这就不是不可变对象了
//尝试Object3不可变性的测试
int[] arr2 = new int[]{1,2};
Object3 obj3 = new Object3(arr2);//传递的是数组的地址(堆地址)
System.out.println(obj3);
arr2[0]= 2;//改了
System.out.println(obj3);//此处不会变化,这就是不可变对象了,因为之前已经copy过了,即在堆中构建了新的对象*/
}
}
输出如下:
由输出可以看出一些东西,由于值传递的原因,若修改值传入的地址所在数组的内容,会导致对象也会发生变化,而只传入copy数组的话相当于创建了一个新的数组,修改原数组自然不会对地址造成影响了,即可认为若构造函数时使用匿名数组也可达到不可变性的目的,科科~