代码之家  ›  专栏  ›  技术社区  ›  Will Ganeshgm7

在Java中,什么是浅拷贝?

  •  47
  • Will Ganeshgm7  · 技术社区  · 17 年前

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

    正如回答的那样,这似乎不是一个肤浅的副本 here 语言不可知论者,

    在Java中,什么是浅拷贝?

    它与Java深度拷贝(如果存在)有何不同?

    9 回复  |  直到 9 年前
        1
  •  90
  •   Igor Konoplyanko    11 年前

    浅层副本只复制类中引用的值。深度副本复制这些值。鉴于:

    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() ).

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

    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
    
        2
  •  17
  •   Chathuranga Chandrasekara    17 年前

    在深度复制的情况下,将创建内存段的精确副本,并将指针设置到新的内存位置。因此理论上,在这种情况下,内存消耗应该是原来的两倍。

        3
  •  9
  •   mnuzzo    17 年前

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

    Object B = A;
    

    通过获取对象A的属性并将其放入新对象B中,可以创建深度副本。

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

    这会影响程序行为,因为如果创建浅层副本并对其执行任务,则会影响对象的所有浅层副本。如果对深度副本进行更改,则仅该副本受影响。我希望这对你足够详细。

        4
  •  3
  •   Tom Hawtin - tackline    17 年前

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

        5
  •  2
  •   jsight TaherT    17 年前

    这似乎是文档中的一个错误。我看不出Android的Calendar.clone方法如何满足“浅拷贝”的典型定义(用Java或其他语言)。

        6
  •  1
  •   Kevin Montrose    17 年前

    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);
      }
    }
    

    在其克隆()中返回浅层副本。

        7
  •  1
  •   Akanksha    9 年前

    浅复制只是将对象引用复制到目标引用中。它不会在堆上创建新对象。

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

        8
  •  1
  •   user8656194 user8656194    6 年前

    深度复制是按值传递的 上下文不同,但过程完全相同。首先要记住,在Java方法调用中,原语是通过值传递的,而对象是通过引用传递的(在其他语言中,对象也可能是通过值传递的)。现在,在Java中,当调用方将原语传递给被调用的方法时,被调用的方法只是将其克隆为一个新的局部变量,这是一个深度副本。而如果传递了一个对象,被调用的方法将只对同一个对象进行一个新的局部引用,这是浅拷贝。如果您了解呼叫,您就了解深度/浅层复制&反之亦然

        9
  •  0
  •   mark    13 年前

    您可以在此处阅读更多内容: http://www.javapractices.com/topic/TopicAction.do?Id=3

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

    Java中的数组很棘手,这也是因为Java确实通过值传递,但数组的值只是它们的指针!另一方面,这允许我们同步对象,这是一件很棒的事情。但是,如果在数组(或ArrayList)中使用数组,仍然会出现一些问题,因为容器数组(或ArrayList)的克隆()不会复制它们的值,而只复制它们的引用!所以你不应该把任何数组放到数组中,你应该只处理数组中的对象!

    玩得高兴

        10
  •  0
  •   pndey    8 年前

    浅拷贝有一个明显的缺点,克隆对象和原始拷贝引用相同的地址对象。克隆对象在地址对象中所做的任何更改也将反映在原始副本中,这是一种不需要的行为。我们真正想要的是用户对象的两个独立副本。在这种情况下,深度复制是我们的救命稻草。

    您可以在此处查看关于此的工作示例: https://codingninjaonline.com/2017/11/09/deep-vs-shallow-copy/

        11
  •  0
  •   Neeraj    7 年前

    浅复制:在此克隆中,对克隆对象的任何更改也会反映到原始对象。