【问题标题】:Understanding clone method for non-final classes了解非最终类的克隆方法
【发布时间】:2015-07-21 16:07:41
【问题描述】:

我正在阅读 J. Bloch 的有效 java,现在我在第 39 节(制作防御性副本)。他提到通过clone的方法制作防御副本不好,因为:

还要注意,我们没有使用 Date 的 clone 方法来制作 防御副本。因为 Date 不是最终的,所以克隆方法 不是 保证返回一个类为 java.util.Date 的对象:它可以 返回一个不受信任的子类的实例,专为 恶作剧。

强调的陈述对我来说并不明显。实际上,让我们与javadocs 协商。没有关于创建子类的任何参考。我们唯一可以确定的是:

此方法创建该对象的类的新实例,并且 用完全的内容初始化它的所有字段 这个对象的对应字段,就像通过赋值一样;内容 的字段本身没有被克隆。

那么为什么 J. Bloch 说它可以创建子类?您不能从 javadoc 中解释它的含义吗(我自己看不到)。

【问题讨论】:

    标签: java clone


    【解决方案1】:

    它在 Javadocs 引用中是隐含的:“this”对象的类可以是引用该对象的变量的声明类型的子类(由于多态性)。 clone 方法受到保护,因此可以在某个类的子类中调用。

    public class Test {
        public static void main(String[] args) throws Exception {
            Foo foo = new Bar();
            Foo copyOfFoo = createCopyOfFoo(foo);
            System.out.println(copyOfFoo);
        }
    
    
        private static Foo createCopyOfFoo(Foo foo) throws CloneNotSupportedException {
            Foo clone = (Foo) foo.clone();
            return clone;
        }
    }
    
    class Foo implements Cloneable {
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }
    
    class Bar extends Foo {
        private int x = 1;
    
        @Override
        public String toString() {
            return "Bar [x=" + x + "]";
        }
    }
    

    输出:

    条形图 [x=1]

    【讨论】:

    • 但是克隆本身总是返回调用它的动态类类型的实例。所以,如果我们在 excatly java.util.Date 上调用 clone 方法,我们肯定会得到 Date 的 inctance,对吧?
    • 如果在Date类型的对象上调用该方法,那么是的。
    • 我猜他是在假设你不知道你有一个 java.until.Date 而不是一个子类。该子类可以实例化另一个不受信任的子类并返回它(不遵守 clone() 的约定)。
    • 我还是没明白...如果我使用会发生什么问题
    猜你喜欢
    • 2015-09-12
    • 1970-01-01
    • 1970-01-01
    • 2019-01-21
    • 1970-01-01
    • 1970-01-01
    • 2016-08-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多