问题
今天在写leetcode的时候看到了这样一个例子:
StringBuilder[] a = new StringBuilder[5];
Arrays.fill(a, new StringBuilder("asdfg"));
a[0].deleteCharAt(0);
for (StringBuilder s : a) {
System.out.println(s);
}
和输出
sdfg
sdfg
sdfg
sdfg
sdfg
底下的人解释说是因为fill方法是将Object引用分配给指定的数组中的每个元素,所以当改变数组中其中一个元素时,别的元素也会同时改变,因为他是同一个。
然后我略加思索,敲出了下面的代码:
int b = 1;
int[] a = new int[5];
Arrays.fill(a, b);
b = 2;
System.out.println(Arrays.toString(a));
但是结果却是
[1, 1, 1, 1, 1]
原理
为什么就没发改变了呢?这就牵扯到一个有意思的东西了:
1、如果变量是基本数据类型,此时赋值的是变量所保存的数据值.
于是
int a1=1;int a2=a1
是两个内存空间中有两个1,他们相等.
2、如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值,于是
StringBuilder a1 = new StringBuilder();
StringBuilder a2 = new StringBuilder();
a2=a1
是两个内存空间现在指向了同一个地址,他们的内容是同一个内容。
回到上述的问题中,为什么第一段代码改变了而第二段代码没有改变呢?
我认为根本就不是那个人说的“因为fill方法是将引用分配给数组中的每一个元素”,而是因为fill方法的本质相当于“=”号,当你使用Arrays.fill(a, new StringBuilder("asdfg"));
时,“=”号将此对象的地址赋值给了a数组中的所有元素。而当你使用Arrays.fill(a, b);
时,“=”号只是将b的值赋值给了a数组中的所有元素。所以当你a[0].deleteCharAt(0);
时,地址中的值发生了改变,所以所有元素都发生了改变。而当你改变b的值时,a自然不会变。
参考
链接: Java核心技术系列之华东师范大学Java核心技术第四章对象与类,话谈Java中的赋值与变量交换底层原理、构造函数、信息隐藏、this
问题原文:
链接: 在java中的StringBuilder数组中操作StringBuilder