在Java中,什么是浅拷贝?

Wil*_*ill 51 java clone shallow-copy

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

为回答这并不似乎是一个浅拷贝这里的SO.这个问题被标记为与语言无关, Java似乎不遵循语言无关的定义.当我单步执行代码时,我注意到结构和元素被复制到这个新对象,而不仅仅是语言无关的结构.

在Java中,什么是浅拷贝?

它与Java深层副本(如果存在)有何不同?

Kit*_*YMG 78

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

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  
Run Code Online (Sandbox Code Playgroud)

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

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

C-主义

int a = 10; //init
int& b = a; //shallow - copies REFERENCE
int c = a;  //deep - copies VALUE
++a;
Run Code Online (Sandbox Code Playgroud)

结果:

a is 11  
*b is 11  
c is 10
Run Code Online (Sandbox Code Playgroud)

  • 要看.`newFoo.bar = newBar`只会改变`newFoo`的`bar`,而不是'foo`.但是`newFoo.bar.avalue = 1`会改变两者. (2认同)

Cha*_*ara 15

浅拷贝只是一组指向相同内存位置的指针.实际上它不会创建真正的副本,因此内存使用率较低.

在深拷贝的情况下,创建内存段的精确副本,并将指针设置为新的内存位置.因此理论上,在这种情况下,内存消耗应该是两倍.

  • 这是一个Java问题而不是C/C++问题,因此关于内存段的讨论会产生误导. (6认同)
  • 放松,斯蒂芬......对于来自C/C++背景的人来说,Chathuranga的答案实际上有所帮助.对同一问题有不同的看法是好的. (3认同)
  • 不要认为那么高的水平。无论使用哪种语言,您都在处理物理硬件,例如内存和CPU。即使我们不使用alloc,malloc也不认为我们没有在Java中使用内存。 (2认同)

mnu*_*zzo 6

浅拷贝是指向对象的引用指针的副本,而深拷贝是对象本身的副本.在Java中,对象保留在后台,通常在处理对象时与之交互的是指针.变量名称指向对象的内存空间.当您将一个变量设置为另一个变量时,会生成浅复制,如下所示:

Object B = A;
Run Code Online (Sandbox Code Playgroud)

可以通过获取对象A的属性并将它们放入新对象B来制作深度副本.

Object B = new Object(A.getProperty1(), A.getProperty2()...);
Run Code Online (Sandbox Code Playgroud)

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

  • 那是不对的 .如果你正在做对象B = A,你就是别名A.这不是浅拷贝,而是这只是一个赋值.如果你做A.clone()并将它分配给B,那将是浅拷贝的正确定义. (3认同)