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

我做了两次测试,第一次是从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 list1 = new ArrayList(); List list2 = list1; list1.add(1); System.out.println(list1.size()); //1 System.out.println(list2.size()); //1 

此示例list2 = list1, by reference指示list2 = list1, by reference

我很困惑, which Java variables/objects是按value传递的,哪些是通过reference传递的?

在你的第一个代码中,是的,这一行

 String str2 = str1; 

str2分配给str1引用的相同String ,即"old" 。 此时,它们是同一个对象。 但是,下一行

 str1 = "new"; 

创建一个String实例,并将str1的引用更改为此新String。 由于我们正在更改str1的引用,因此str2的内容不会更改。

注意Java, String是不可变的,即初始化后不能改变状态。 以这种方式思考, "old"内容可能永远不会改变。 因此,当您为str1指定"new"时,不会更改"old"的值,而是创建一个新的String

换句话说,这一行与此相同

 str1 = new String("new"); 

http://sofzh.miximages.com/java/jboQoqCxApSELU.png

但是,在第二个代码中,

 List list2 = list1; 

make list2引用与list1相同的列表。 因此, list1list2引用相同的列表。 然后

 list1.add(1); 

将一个元素添加到list1引用的列表中。 但是,正如我所说, list1list2引用相同的列表, list1list2现在都有元素1 。 方法调用中没有创建新实例。

http://sofzh.miximages.com/java/jxDLyBqcUzgHZ.png

事实上,如果你这样做的话

 List list1 = new ArrayList(); List list2 = list1; list1 = new ArrayList(); list1.add(1); System.out.println(list1.size()); //1 System.out.println(list2.size()); //0 

因为list1 = new ArrayList();list1重新分配给新列表,该列表不再引用list2引用的对象。


在所有赋值运算符(即obj1 = obj2 )之后总是复制引用,这两个引用在赋值后仍将引用相同的对象实例。 这适用于StringList任何其他类 (但不是基本类型)。

但是,在大多数情况下, str1 = "new"将创建一个新的String实例,然后将对新String的引用分配给str1 – 这是Java语言中的一个特例。 这不适用于任何其他类型的对象。 这与list1.add(1)等任何其他方法调用不同。

你的不同之处在于此

 str1 = "new"; 

VS

 list1.add(1); 

String示例中,您正在更改引用。 更改str1的引用不会影响任何其他变量。

List示例中,您正在调用一个方法,该方法取消引用该引用并访问该对象。 引用该同一对象的任何变量都将看到该更改。

这里是

 List list1 = new ArrayList(); // 1 List list2 = list1; // 2 list1.add(1); // 3 

看起来像这样

  1: list1 ===> object1234 2: list1 ===> object1234 <=== list2 3: list1 ===> object1234 (internal modification) <=== list2 

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. 

在列表的情况下,两个列表都指向相同的存储器位置,因此反映了变化。

Java都是通过值传递的。 Java没有通过引用传递。 副本传递给可能是方法参数或常规普通变量的变量。 字符串文字,字符串,数组引用和ArrayLists等对象仍将按值传递。

问题是如果没有重新分配引用,那么引用变量将发生在它引用的对象上。

从这里编写头像java和其他书籍的人那里查看本教程: http : //www.javaranch.com/campfire/StoryPassBy.jsp

还有你的代码OP,请记住字符串是不可变的。 这意味着一旦创建了对象,它基本上不会改变。 在您的代码中虽然重新分配了String引用,而List引用只是有一个名为on的方法。 List引用都指向完全相同的ArrayList对象; 所以方法调用size()影响两个List引用,因为它们都指向堆内存中的同一个对象。 :d

快乐的编码!