java clone():ArrayList。克隆人()我认为它是一个肤浅的复制品
ArrayList<Integer> a=new ArrayList<Integer>();
a.add(5);
ArrayList<Integer> b=(ArrayList<Integer>)a.clone();
a.add(6);
System.out.println(b.toString());
在上面的代码中,我认为clone()
做了一个肤浅的复制。所以,b
和a
应该指向相同的内存位置。然而,当我做b.toString()
时,答案只是5
。如果clone()
进行浅层复制,为什么6
也不显示
# 1 楼答案
这确实是一个浅拷贝,这里是对克隆的注释,来自ArrayList源代码
为了理解这一点,让我们看看ArrayList中克隆方法中的一个片段
正如我们所知,当我们将一个对象分配给一个变量时,JAVA并不会生成一个全新的 那个物体。相反,该变量成为指向原始对象的另一个引用
因此,elementData实际上存储了对放入该ArrayList的对象的引用。克隆 复制这些引用时,不会创建对象的副本
当然,您可以删除或添加对克隆ArrayList的新引用
但是,修改一个ArrayList中的旧对象会影响原始ArrayList。因为整数是不可变的,所以很难用你的例子来说明
要查看副作用,可以定义自定义可变对象
然后可以使用以下代码进行测试
输出应该是
看到副作用了吗?我们只改变yy中的元素,但它也反映在tt中
# 2 楼答案
我们不能像这样动态地选择要添加字符串的位置吗
它不是在读取整数后执行
# 3 楼答案
如果它像你想的那样,那么
clone
方法将是完全无用的,因为在这种情况下,以下几行将是等效的:与现实场景一样,克隆是一个创建两个属性完全相同的实体的过程(在克隆操作时)
正如Bozho提到的——避免Java{}概念。即使是作者提到的,它也坏了
This question and it's answers非常有价值,并提供一个链接,链接到Josh Blochs自己对其作品的评论;-)
# 4 楼答案
浅拷贝并不意味着它们指向同一个内存位置。那只是一个任务:
List b = a;
克隆会创建一个新的实例,其中包含相同的元素。这意味着你有两个不同的列表,但它们的内容是相同的。如果在第一个列表中更改对象的状态,它将在第二个列表中更改。(因为您使用的是不可变类型-
Integer
,所以无法观察到这一点)但是,您应该考虑不使用^ {CD3>}。它适用于收藏,但通常被认为是破损的。使用复制构造函数-
new ArrayList(originalList)
# 5 楼答案
Arraylist中的clone函数与将一个Arraylist复制到另一个Arraylist不同,如果使用clone(),它会保留原始Arraylist的副本,但如果在使用clone()后对原始Arraylist进行任何更改,则不会影响复制的Arraylist。。 例如:
输出:-
[A]
[A]
[]
[A]
# 6 楼答案
浅层克隆是
Object.clone()
提供的默认克隆策略。 object类的clone()
方法创建一个新实例,并将可克隆对象的所有字段复制到该新实例(要么是基元实例,要么是引用实例)。因此,在引用类型的情况下,只有引用位被复制到新实例,因此,两个对象的引用变量将指向同一个对象。我们上面看到的例子是一个浅层克隆的例子深度克隆顾名思义,深度克隆意味着从一个对象克隆到另一个对象。为了实现这一点,我们需要欺骗我们的
clone()
方法来提供我们自己的克隆策略。我们可以通过实现Cloneable
接口,在对象层次结构中的每个引用类型中重写clone()方法,然后在对象的clone方法中调用super.clone()
和这些clone()
方法来实现但是,如果你在源代码中查看ArrayList的clone()方法,你会发现它在调用
super.clone()
后从外部复制v.elementData = Arrays.copyOf(elementData, size);
,这意味着ArrayList的clone()会深度复制它的内容要阅读有关克隆及其类型(如深度克隆和浅层克隆)的更多信息,请阅读Java Cloning and Types of Cloning (Shallow and Deep) in Details with Example