如何使用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
。