在Java中,什么是浅拷贝?

java.util.Calendar.clone()返回“…具有相同属性的新日历”并返回“此日历的浅表副本”。

这似乎不是一个浅显的副本,就像在SO上回答的那样。 这个问题被标记为与语言无关, Java似乎没有遵循语言不可知的定义。 当我遍历代码时,我注意到结构和元素被复制到这个新的对象,而不仅仅是语言不可知的结构。

在Java中,什么是浅拷贝?

它与Java深层复制(如果存在的话)有什么区别?

浅拷贝只是复制类中引用的值。 深拷贝复制值。 给定:

class Foo { private Bar myBar; ... public Foo shallowCopy() { Foo newFoo = new Foo(); newFoo.myBar = myBar; return newFoo; } public Foo deepCopy() { Foo newFoo = new Foo(); newFoo.myBar = myBar.clone(); //or new Bar(myBar) or myBar.deepCopy or ... return newFoo; } } Foo myFoo = new Foo(); Foo sFoo = myFoo.shallowCopy(); Foo dFoo = myFoo.deepCopy(); myFoo.myBar == sFoo.myBar => true myFoo.myBar.equals(sFoo.myBar) => true myFoo.myBar == dFoo.myBar => **false** myFoo.myBar.equals(dFoo.myBar) => true 

在这种情况下,浅拷贝具有相同的引用( == ),而深拷贝只具有相同的引用( .equals() )。

如果对浅拷贝引用的值进行了更改,则副本会反映该更改,因为它共享相同的引用。 如果对深度复制引用的值进行更改,则副本不会反映该更改,因为它不共享相同的引用。

C-主义

 int a = 10; //init int& b = a; //shallow - copies REFERENCE int c = a; //deep - copies VALUE ++a; 

结果:

 a is 11 *b is 11 c is 10 

浅拷贝只是一组指向相同内存位置的指针。 实际上它不会创build一个真正的副本,所以内存使用率较低。

在深度复制的情况下,创build内存段的精确副本,并将指针设置为新的内存位置。 所以在这种情况下,理论上内存消耗应该是两倍。

浅拷贝是指向对象的引用指针的副本,而深拷贝是对象本身的副本。 在Java中,对象保留在后台,通常在处理对象时与之交互的是指针。 variables名称指向对象的内存空间。 当你设置一个variables等于另一个variables时,就会产生一个浅拷贝:

 Object B = A; 

可以通过获取对象A的属性并将它们放入新的对象B来进行深层复制。

 Object B = new Object(A.getProperty1(), A.getProperty2()...); 

这会影响程序的行为,因为如果您制作浅度副本并对其执行任务,则会影响对象的所有浅度副本。 如果您对深层副本进行更改,则只会影响该副本。 我希望这对你来说已经足够详细了。

1.6文档Calendar.clone文件为“创build并返回此对象的副本”。 Object.clone指定的文字浅拷贝没有任何意义。 Java在相当典型的意义上使用术语“浅拷贝”。

在文档中似乎是一个错误。 我没有看到Android的Calendar.clone方法如何满足“浅拷贝”的典型定义(以Java或其他方式)。

你在哪里得到这个文件?

java.sun.com上的官方Java 6文档只是使用Calendar.clone()返回对象的副本。 没有提到浅。

更一般地说,Java中的浅拷贝就是你得到一个新的对象引用的地方,但是新对象持有(直接或间接)引用原始数据。

例如:

 class MyClass{ private List<Integer> innerList; public MyClass(List<Integer> list) { innerList = list; } //Some code... public Object clone(){ return new MyClass(innerList); } } 

在其clone()中返回一个浅表副本。

首先,如果我们谈论一维数组,那么ArrayList的Javadoc有点不对,因为它使用数组中的copyOf方法。 所以clone()给出了一个一维的副本,至less从1.5(我没有进一步testing)! 所以这就是Java中“浅”的含义:一维

你可以在这里阅读更多: http : //www.javapractices.com/topic/TopicAction.do?Id=3 。 所以clone()不是浅拷贝! 如果你想要一个一维数组的真正的浅拷贝,只需引用它:

 Array a = new Array(); Array b = a; //a is only a shallow copy, nice for synchronisation 

Java中的数组是非常棘手的,也是因为Java传递值,但是数组的值只是它们的指针! 另一方面,这允许我们同步对象,这是一件好事。 但是,如果在数组(或ArrayList)中使用数组,则存在一些问题,因为容器数组(或ArrayList)的clone()将不会复制它们的值,只有它们的引用! 所以你不应该把任何数组放到数组中,你应该只处理数组中的对象!

Javadoc有时候很难理解,所以试一试

玩的开心!

浅拷贝只是将对象引用复制到目标引用中。 它不会在堆上创build新的对象。 默认情况下,Java使用clone()函数进行浅层克隆。

为了在堆上获得新的对象,必须执行深度克隆,这可以通过序列化和反序列化来实现。

在浅拷贝中,克隆对象具有原始值的副本,但对象引用指向与原始副本相同的对象。 浅拷贝有一个明显的缺点,克隆对象和原拷贝引用同一个地址对象。 克隆对象在地址对象中所做的任何更改都将反映在原始副本中,这是不受欢迎的行为。 我们真正想要的是用户对象的两个单独的副本。 深度复制是为了解决这种情况。

深拷贝克隆不仅仅是原始值,它还创build对象引用的副本。

你可以看看这里的工作示例: https : //codingninjaonline.com/2017/11/09/deep-vs-shallow-copy/