Java 为什么一个arraylist的副本被修改时会发生更改
这可能是一个非常简单的问题,但它仍然让我困惑Java 为什么一个arraylist的副本被修改时会发生更改,java,Java,这可能是一个非常简单的问题,但它仍然让我困惑 import java.util.ArrayList; public class Sample { ArrayList<Integer> i = new ArrayList<>(); ArrayList<Integer> j = new ArrayList<>(); /** * @param args */ public static void m
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);
}
}
为什么当我改变时j会改变?但在原语中不会发生这种情况 语句
j=i代码>将引用j
指定为与i
相同的引用。现在i
和j
都引用相同的ArrayList
对象。删除第0个索引只需通过两个引用即可看到
如果希望删除i
中的项目不会影响j
中的列表,请创建列表的副本,而不是分配引用:
j = new ArrayList<Integer>(i);
j=新数组列表(i);
(这是一个浅表副本,因此列表仍然引用相同的元素。)使用
j = new ArrayList<>(i);
创建一个副本
使用j=i
时,您只能在i
上指向j
(称为参考)。这适用于所有涉及对象的赋值(不是像int
或float
这样的基本类型)对象未克隆,只是添加了一个附加的对象引用。由于ArrayList不是不可变的,因此对对象的任何更改都会反映在对象引用中。对象和原语的工作方式有所不同。将像i
这样的对象视为该对象的名称。当你说j=i
时,你是在告诉JVM“忘记我说的另一个名为j
的ArrayList
;从现在起,当我提到j
时,我指的是这个ArrayList
,也可以称为I
。事实上,事情就是这样:在这一行之后,两个变量都指向同一个对象
原语按您所说的那样工作。如果你说i=5;j=i;i=6
,则j
仍将设置为5。您为j创建了一个内存阶段,其中包含;j=新的ArrayList()<然后你说让j指的是我的记忆阶段。所以在j=i之后;i或j上的任何更改都将影响它们。因为它们引用相同的对象。让我用以下方式为您执行此操作:
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));
事实上,所有对象(可变的)都会发生这种情况。在Java中,所有对象都是通过引用传递的,而不是原语类型。(我更正:)@meskobalazs Java中的一切都是通过值传递的。对于对象,引用是通过值传递的。@meskobalazs请参见。是的,我应该更具体一些。您应该搜索Java如何处理内存,特别是对象引用,以及浅复制和深复制之间的区别。
Collections.copy(j, i);
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));
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