我做了两次测试,第一次以Strings
String str1 = "old";
String str2 = str1;
str1 = "new";
System.out.println(str1); //new
System.out.println(str2); //old
以上示例表明str2 = str1, by value
现在我进行类似的操作,但这次是Lists
List<Integer> list1 = new ArrayList<Integer>();
List<Integer> list2 = list1;
list1.add(1);
System.out.println(list1.size()); //1
System.out.println(list2.size()); //1
此示例表示list2 = list1, by reference
我很困惑,which Java variables/objects
由value
传递,并由reference
传递?
答案 0 :(得分:4)
你的不同之处在于
str1 = "new";
vs
list1.add(1);
在String
示例中,您正在更改引用。更改str1
的引用不会影响任何其他变量。
在List
示例中,您正在调用一个方法,该方法取消引用该引用并访问该对象。引用该同一对象的任何变量都将看到该更改。
这是
List<Integer> list1 = new ArrayList<Integer>(); // 1
List<Integer> list2 = list1; // 2
list1.add(1); // 3
看起来像这样
1: list1 ===> object1234
2: list1 ===> object1234 <=== list2
3: list1 ===> object1234 (internal modification) <=== list2
答案 1 :(得分:3)
在你的第一个代码中,是的,这一行
String str2 = str1;
将str2
分配给String
引用的同一str1
,即"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;
make 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()); //1
System.out.println(list2.size()); //0
因为list1 = new ArrayList<Integer>();
将list1
重新分配给新列表,不再引用list2
引用的对象。
毕竟赋值运算符(即obj1 = obj2
)总是复制引用,这两个引用仍将在赋值后引用同一个对象实例。这适用于String
,List
或任何其他类(但不是基本类型)。
但是,str1 = "new"
在大多数情况下会创建String
的新实例,然后将对String
的引用分配给str1
- 这是一个特殊的Java语言中的案例。这不适用于任何其他类型的对象。这与list1.add(1)
等任何其他方法调用不同。
答案 2 :(得分:0)
java中的所有东西都是通过Value传递的。没有什么比java.Objects中的refrence传递更多的是通过值传递引用。 在ist的情况下,即
String str1="old"
String str2=str1; //here str2 is pointed to str1
str1="new"; // here link of str1 is broken with old and pinted to new location where as str2 is pointing to same location as earlier.
在列表的情况下,两个列表都指向相同的内存位置,因此反映了更改。
答案 3 :(得分:0)
Java全部按价值传递。 Java没有通过引用传递。副本传递给可能是方法参数或常规普通变量的变量。字符串文字,字符串,数组引用和ArrayLists等对象仍将按值传递。
问题是如果没有重新分配引用,那么引用变量会发生在它引用的对象上。
从这里编写 head first java 和其他书籍的人那里查看本教程:http://www.javaranch.com/campfire/StoryPassBy.jsp
还有你的代码OP,请记住字符串是不可变的。这意味着一旦创建了对象,它基本上不会改变。在您的代码中虽然重新分配了String引用,而List引用只是有一个名为on的方法。 List引用都指向完全相同的ArrayList对象;所以方法调用size()
会影响两个List引用,因为它们都指向堆内存中的同一个对象。 :d
快乐的编码!