它可能是一个非常简单的但它仍然让我感到困惑!
import java.util.ArrayList;
public class Sample {
ArrayList<Integer> i = new ArrayList<>();
ArrayList<Integer> j = new ArrayList<>();
/**
* @param args
*/
public static void main(String[] args) {
new Sample().go();
}
private void go() {
i.add(1);
i.add(2);
i.add(3);
j=i;
i.remove(0);
System.out.println(i + "asd" + j);
}
}
我试图打印它:
[2, 3]asd[2, 3]
当我改变时,为什么j会改变?但是不会发生原语!
答案 0 :(得分:8)
语句j=i;
将引用j
指定为与i
相同的引用。现在,i
和j
都引用了相同的ArrayList
对象。通过两个引用都可以看到删除第0个索引。
如果您希望删除i
中的项目不会影响j
中的列表,请创建列表的副本,而不是分配引用:
j = new ArrayList<Integer>(i);
(它是一个浅的副本,因此列表仍然引用相同的元素。)
答案 1 :(得分:1)
使用
j = new ArrayList<>(i);
或
Collections.copy(j, i);
创建副本。
使用j = i
,您只需j
点i
(称为参考号)。这适用于涉及对象的所有分配(不是int
或float
等基本类型
答案 2 :(得分:1)
未克隆对象,仅添加了其他对象引用。由于ArrayList不是不可变的,因此对象的任何更改都会反映在对象引用中。
答案 3 :(得分:0)
对象和原语的工作方式有所不同。可以将i
之类的对象视为该对象的名称。当你说j=i
你告诉JVM时“忘记我说的其他ArrayList
被称为j
;从现在开始,当我提到j
时,我的意思是这个ArrayList
也可以被称为i
。实际上,这正是发生的事情:在该行之后,两个变量都引用同一个对象。
原始人就像你说的那样工作。如果您说i=5; j=i; i=6
,则j
仍会设为5。
答案 4 :(得分:0)
你为j创建了一个内存阶段; j = new ArrayList&lt;&gt;();
但是你说让j引用我的内存阶段。所以在j = i之后; i或j上的任何变化都将影响它们。因为它们引用了相同的对象。
答案 5 :(得分:0)
让我以下列方式为您做到这一点:
ArrayList<Integer> i = new ArrayList<>();
ArrayList<Integer> j = new ArrayList<>();
// checking hash code before j = i;
System.out.println(System.identityHashCode(i));
System.out.println(System.identityHashCode(j));
j = i;
// checking hash code after j = i;
System.out.println(System.identityHashCode(i));
System.out.println(System.identityHashCode(j));
比较两个值是否相同,这意味着j=i;
ArrayList j
现在指向ArrayList i
在我的机器上o / p是:
30269696 //hashCode of i
24052850 //hashCode of j before j = i;
30269696 //hashCode of i and j are same after j = i that means they are pointing to same reference and hence change in one reflects on the other.
30269696