当超类不可克隆时覆盖 Java 中的 Clone() 方法

Overriding Clone() method in Java when superclass is not Clonable

How to clone a Java object with the clone() method

我有一个关于在 java 中为 class 正确实施 clone() 方法的问题。 我知道这是不好的做法,但我需要知道这个才能参加考试。 在上面的讨论中,他们说要调用 super.clone() - 但我不明白如果超级函数没有实现 Clonable 会发生什么。 例如,假设我有一个扩展 Y 的 class X。X 实现了 Clonable 而 Y 没有。 Y 的 clone() 方法应该抛出异常。那这种情况我们怎么办呢?

我能以某种方式找到的所有解释都假设所有超级classes 都实现了 Clonable,或者至少我是这么理解的..

编辑:

请查看此代码:

public class Employee implements Cloneable {

private String name;

public Employee(String name) {
    this.name = name;
}

public String getName() {
    return name;
}

public Object clone()throws CloneNotSupportedException{  
    return (Employee)super.clone();  
}

public static void main(String[] args) {
    Employee emp = new Employee("Abhi");
    try {
        Employee emp2 = (Employee) emp.clone();
        System.out.println(emp2.getName());
    } catch (CloneNotSupportedException e) {
        e.printStackTrace();
    }
}

}

取自这里:https://www.javacodegeeks.com/2018/03/understanding-cloneable-interface-in-java.html

在很多教程中都可以找到类似的代码。

当 superclass(在本例中为 Object)未实现 Clonable 时,为什么他们可以使用 super.clone() - 这会导致异常。

Cloneable-interface is generally regarded as broken (and won't be fixed). At the core, the argument revolves around the fact that clone() is a method defined on Object, instead of being a method of the interface Cloneable.

我根本不推荐使用它。更好的解决方案是提供 copy-constructors。如果没有能力完全重新创建一个父对象-class,那么克隆是不可能的。

重构所提供的代码将导致类似于此的结果:

public class Employee implements Cloneable {

    private String name;

    public Employee(String name) {
        this.name = name;
    }

    public Employee(Employee that) {
        this.name = that.name;
    }

    public static void main(String[] args) {
        Employee emp = new Employee("Abhi");
        Employee emp2 = new Employee(emp);
        System.out.println(emp2.getName());
    }

    public String getName() {
        return name;
    }
}

对您的代码的评论:

public class Employee {
    public Object clone()throws CloneNotSupportedException{  
        return (Employee)super.clone();  
    }
}

类型转换是多余的,因为方法 returns 和 Object.

如果你有这样的结构:

class Y {}

class X extends Y implements Cloneable {
    @Override
    public X clone() {
        try {
            return (X) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e);
        } 
    }
}

然后在 X 的实例上克隆将正常工作。 它不适用于 Y 的直接实例,因为它们未声明为可克隆。但是 X 上的 Cloneable 接口是默认 clone() 实现机制的指示器,它们应该起作用。

或者

只要不依赖 clone().[=24 的默​​认实现,您也可以使用具有有效 clone() 方法的不可克隆 class =]

例如:

class Y {
    @Override
    public Y clone() {
        // Don't call super.clone() because it will error
        return new Y(...); // whatever parameters
    }
}

然而,使用这个机制,如果你从Y的子class调用super.clone(),你会得到一个实例Y,这可能不是您想要的。

正如其他人指出的那样,Cloneable 机制笨拙且令人困惑,通常使用 new 的复制机制更容易使用。