在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
相同的列表。 因此, list1
和list2
引用相同的列表。 然后
list1.add(1);
将一个元素添加到list1
引用的列表中。 但是,正如我所说, list1
和list2
引用相同的列表, list1
和list2
现在都有元素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
)之后总是复制引用,这两个引用在赋值后仍将引用相同的对象实例。 这适用于String
, List
或任何其他类 (但不是基本类型)。
但是,在大多数情况下, 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
快乐的编码!