当超类不可克隆时,在 Java 中重写 Clone() 方法



如何使用clone((方法克隆Java对象

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

我能找到的所有解释都以某种方式假设所有超类都实现了可克隆,或者至少这是我所理解的。

编辑:

请查看此代码:

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

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

为什么当超类(在本例中为Object(不实现可克隆时,他们可以使用super.clone()- 这将导致异常。

如果您有此结构:

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()方法的非克隆类,只要您不依赖于clone()的默认实现。

例如:

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

但是,使用这种机制,如果您从Y的子类调用super.clone(),您将获得Y的实例,这可能不是您想要的。

正如其他人所指出的,Cloneable机制是笨拙和混乱的,通常使用new复制机制更容易使用。

Cloneable接口通常被认为是损坏的(并且不会被修复(。在核心,论证围绕着这样一个事实,即clone()是在Object上定义的方法,而不是接口Cloneable的方法。

我根本不建议使用它。更好的解决方案是提供复制构造函数。如果无法完全重新创建父类对象,则克隆是不可能的。

重构提供的代码将导致类似于以下内容的结果:

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

类型强制转换是多余的,因为方法返回一个Object

最新更新