在Java中设置相等:按值或引用?

时间:2014-03-05 04:39:01

标签: java string list reference

我做了两次测试,第一次以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/objectsvalue传递,并由reference传递?

4 个答案:

答案 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相同的列表。因此,list1list2引用相同的列表。然后

list1.add(1); 

将一个元素添加到list1引用的列表中。但是,正如我所说,list1list2引用相同的列表,list1list2现在都有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总是复制引用,这两个引用仍将在赋值后引用同一个对象实例。这适用于StringList任何其他类(但不是基本类型)。

但是,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

快乐的编码!