在你的第一段代码中,是的,这一行
String str2 = str1
将str2
分配给与str1
引用的相同的String
,即"old"
。此时,它们是同一个对象。但是,接下来的一行
str1 = "new"
创建一个
String
类的
新实例,并将
str1
的引用更改为这个新的字符串。由于我们正在更改
str1
的引用,所以
str2
的内容并不会改变。
需要注意的是,在Java中,
String
是不可变的,即一旦初始化就不能更改状态。按照这种思路,
"old"
的内容可能永远不会改变。因此,当您将
"new"
分配给
str1
时,您并没有改变
"old"
的值,而是创建了一个新的
String
。
换句话说,这行代码与此处相同:
str1 = new String("new");
http://i.minus.com/jboQoqCxApSELU.png
然而,在第二段代码中,
List<Integer> list2 = list1;
使list2
引用与list1
相同的列表。结果,list1
和list2
引用相同的列表。
list1.add(1);
向由list1
引用的列表添加一个元素。但是,正如我所说的,list1
和list2
引用同一个列表,因此list1
和list2
现在都有元素1
。在方法调用中没有创建新实例。
http://i.minus.com/jxDLyBqcUzgHZ.png
事实上,如果你这样做
List<Integer> list1 = new ArrayList<Integer>();
List<Integer> list2 = list1;
list1 = new ArrayList<Integer>();
list1.add(1);
System.out.println(list1.size());
System.out.println(list2.size());
因为
list1 = new ArrayList<Integer>();
会将
list1
重新分配给一个新的列表,那个新列表不再指向
list2
所指向的对象。
在所有情况下,赋值运算符(即
obj1 = obj2
)始终复制引用,这两个引用在赋值后仍然引用同一对象实例。这适用于
String
、
List
或
任何其他类(但不适用于基本类型)。
然而,在大多数情况下,
str1 = "new"
会创建一个
String
的新实例,然后将引用分配给新的
String
- 这是Java语言的特例。这不适用于其他任何类型的对象。这与任何其他方法调用(如
list1.add(1)
)不同。
str1 = "new"
将一个新对象赋给了变量;但list1.add(1)
修改了一个已存在的对象,而不创建新对象。 - Dawood ibn Kareem