【问题标题】:clone() method in JavaJava中的clone()方法
【发布时间】:2011-06-17 11:04:40
【问题描述】:

据我了解,clone() 方法使我们能够在 Java 中复制对象(无引用)。但我也读到,副本很浅。那么有什么意义呢? clone() 方法给了我哪些能力,而简单的评估却没有?

【问题讨论】:

    标签: java


    【解决方案1】:

    不同的是,你可以修改克隆的对象而不修改原始对象。

    Point p = new Point(1,2);
    Point p2 = p.clone();
    Point p3 = p;
    p2.x = 5;
    p3.y = 7;
    

    p3 上的更改会反馈给p,而p2 上的更改不会。

    让我们看看个别语句之后的情况如何(假设1257 是对象):

    Point p = new Point(1,2);
    
                .-----.    .-----.
     p  ----->  |  x -+--> |  1  |
                |     |    '-----'
                |     |    .-----.
                |  y -+--> |  2  |
                '-----'    '-----'
    
    
    Point p2 = p.clone();
    
                .-----.    .-----.    .-----.
     p  ----->  |  x -+--> |  1  | <--+- x  |  <----- p2
                |     |    '-----'    |     |
                |     |    .-----.    |     |
                |  y -+--> |  2  | <--+- y  |
                '-----'    '-----'    '-----'
    
    Point p3 = p;
    
                .-----.    .-----.    .-----.
     p  ----->  |  x -+--> |  1  | <--+- x  |  <----- p2
                |     |    '-----'    |     |
                |     |    .-----.    |     |
     p3 ----->  |  y -+--> |  2  | <--+- y  |
                '-----'    '-----'    '-----'
    
    
    p2.x = 5;
    
                .-----.    .-----.    .-----.    .-----.
     p  ----->  |  x -+--> |  1  |    |  x -+--> |  5  |
                |     |    '-----'    |     |    '-----'
                |     |    .-----.    |     |
     p3 ----->  |  y -+--> |  2  | <--+- y  |  <----- p2
                '-----'    '-----'    '-----'
    
    
    p3.y = 7;
    
                .-----.    .-----.    .-----.    .-----.
     p  ----->  |  x -+--> |  1  |    |  x -+--> |  5  |
                |     |    '-----'    |     |    '-----'
                |     |    .-----.    |     |
     p3 ----->  |  y  |    |  2  | <--+- y  |  <----- p2
                '--+--'    '-----'    '-----'
                   |     .-----.
                   '---> |  7  |
                         '-----'
    

    【讨论】:

    • 谢谢,但我不明白为什么 p2.x 不会改变 p 中的任何内容。没错,我们有 2 个不同的对象,但它们指向相同的 x 和 y(因为浅拷贝)。我错过了什么?
    • 赋值(在最后两行)改变了 xy 指向的内容。即使p.xp2.x 具有相同的值(指的是同一个对象),它们也是不同的变量,赋值给一个不会改变另一个。 (在这种情况下,它们甚至不是对象,而是原始值,但如果它们是对象,同样的事情也是有效的。)
    • 在这个例子中,我们看不到浅克隆和深克隆的区别。
    • @Subhra:如果您可以将数字 1 的“值”更改为其他值,这将显示在使用此数字的所有对象中。但是数字(即这里的整数,假设 java.awt.Point 或类似的东西)是不可变的 - 您可以更改变量的内容(每个赋值),但不能更改 1 的值(否则编写可靠的程序会非常复杂)。
    【解决方案2】:

    赋值将实例的引用复制到变量。 clone 操作将克隆实例(并为克隆分配一个引用)。

    使用 assignment,您将得到 多个 变量指向 一个 对象,通过克隆,您将拥有 多个 持有多个对象引用的变量。

    SomeCloneable a = new SomeCloneable();
    SomeCloneable b = a;                     // a and b point to the same object
    
    /* versus */
    
    SomeCloneable a = new SomeCloneable();
    SomeCloneable b = a.clone();             // a and b point to the different objects
    

    【讨论】:

    • Cloneable 不会公开 clone() 方法。您必须将您的ab 声明为SomeCloneable
    【解决方案3】:

    一个简单的分配将简单地为对象创建一个别名。使用clone(),每个属性成员也将在克隆对象中初始化。但是,如果属性成员本身包含更多对象,则不会复制这些对象。

    【讨论】:

      【解决方案4】:

      浅拷贝是对象的默认。您可以覆盖克隆以进行深层复制。

      【讨论】:

        【解决方案5】:

        要深入克隆,您必须实现 Cloneable 并覆盖 clone()

        public class MyClass implements Cloneable {
        
        private Object attr = new Object();
        
        @Override
        public Object clone() throws CloneNotSupportedException {
            MyClass clone = (MyClass)super.clone();
            clone.attr = new Object();
            return clone;
        }
        
        @Override
        public String toString() {
            return super.toString()+", attr=" + attr;
        }
        
        public static void main(String[] args) throws Exception {
            MyClass x = new MyClass();
            System.out.println("X="+x);
            MyClass y = (MyClass)x.clone();
            System.out.println("Y="+y);
        }
        

        }

        【讨论】:

          猜你喜欢
          • 2015-07-16
          • 2018-06-10
          • 2013-06-16
          • 1970-01-01
          • 2011-03-11
          • 2014-05-19
          • 2015-05-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多