Java克隆抽象对象

我想知道是否有任何方法可以做到以下几点。 我有一个抽象类, Shape ,以及它的所有不同的子类,我想重写克隆方法。 我想在方法中做的就是从当前的toString()创建一个新的Shape 。 显然我不能做以下因为Shape是抽象的。 还有另一种方法可以做到这一点,因为在每个子类中重写克隆只是为了简单的名称更改似乎没用。

 public abstract class Shape { public Shape(String str) { // Create object from string representation } public Shape clone() { // Need new way to do this return new Shape(this.toString()); } public String toString() { // Correctly overriden toString() } } 

您可以尝试使用reflection:

 public abstract class AClonable implements Cloneable{ private String val; public AClonable(){ } public AClonable(String s){ val=s; } public String toString(){ return val; } @Override public AClonable clone(){ try { System.out.println(getClass().getCanonicalName()); AClonable b= getClass().getDeclaredConstructor(String.class).newInstance(val); return b; } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } 

}

在clone()方法中,您调用getClass()。 因为ACloneble是抽象的,所以调用将总是进入具体类。

  public class ClonebaleOne extends AClonable{ public ClonebaleOne(){ super(); } public ClonebaleOne(String s) { super(s); // TODO Auto-generated constructor stub } 

}

  public class ClonebaleTwo extends AClonable{ public ClonebaleTwo(){ super(); } public ClonebaleTwo(String s) { super(s); // TODO Auto-generated constructor stub } 

}

最后

  public static void main(String[] args){ AClonable one = new ClonebaleOne("One"); AClonable tow= new ClonebaleTwo("Two"); AClonable clone = one.clone(); System.out.println(clone.toString()); clone = tow.clone(); System.out.println(clone.toString()); } 

输出:

  ClonebaleOne One ClonebaleTwo Two 

但它更像是一个黑客而不是一个解决方案

[编辑]我的两个克隆比…更快

[编辑]完成。 clone()的另一个实现可以是

  @Override public AClonable clone(){ try { ByteArrayOutputStream outByte = new ByteArrayOutputStream(); ObjectOutputStream outObj = new ObjectOutputStream(outByte); ByteArrayInputStream inByte; ObjectInputStream inObject; outObj.writeObject(this); outObj.close(); byte[] buffer = outByte.toByteArray(); inByte = new ByteArrayInputStream(buffer); inObject = new ObjectInputStream(inByte); @SuppressWarnings("unchecked") Object deepcopy = inObject.readObject(); inObject.close(); return (AClonable) deepcopy; } catch (Exception e) { e.printStackTrace(); } return null; } 

当您的抽象类实现Serialazable时。 在那里,您将对象写入光盘并使用光盘中的值创建副本。

您无法创建abstract类的深层克隆 ,因为它们无法实例化 。 您可以通过使用Object.clone()或返回this来进行浅层克隆

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

要么

 @Override public Object clone() throws CloneNotSupportedException { return this; } 

抽象类可以作为引用,它不能有一个实例,所以在这种情况下浅克隆工作

要么

作为一种更好的方法,您可以将clone()声明为abstract并让子类定义它,就像这样

 abstract class Shape { private String str; public Shape(String str) { this.str = str; } public abstract Shape clone(); public String toString() { return str; } } class Circle extends Shape { public Circle(String str) { super(str); } @Override public Shape clone() { return new Circle("circle"); } } 

虽然我怀疑它是个好主意,但你可以使用reflection:

 import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class Test { public static void main(String[] args) { Square s1 = new Square("test"); Square s2 = (Square) s1.clone(); // show that s2 contains the same data System.out.println(s2); // show that s1 and s2 are really different objects System.out.println(s1 == s2); } public static abstract class Shape { private String str; public Shape(String str) { this.str = str; } public Shape clone() { try { Class cl = this.getClass(); Constructor cons = cl.getConstructor(String.class); return (Shape) cons.newInstance(this.toString()); } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); } return null; } @Override public String toString() { return str; } } public static class Square extends Shape { public Square(String str) { super(str); } } } 

你可以用reflection来解决:

 public abstract class Shape { private String str; public Shape() { } protected Shape(String str) { this.str = str; } public Shape clone() throws CloneNotSupportedException { try { return (Shape)getClass().getDeclaredConstructor(String.class).newInstance(this.toString()); } catch (Exception e) { throw new CloneNotSupportedException(); } } public String toString() { return "shape"; } public class Round extends Shape { public Round() { super(); } protected Round(String str) { super(str); } @Override public String toString() { return "round"; } } main(){ Shape round = new Round(); Shape clone = round.clone(); System.out.println(round); System.out.println(clone); } 

但是 – IMO – 实施效果差,容易出错,有很多坑; CloneableObject.clone()的最佳用法是不使用它们! 你有很多方法可以做同样的事情(如深度克隆的序列化)和浅克隆,可以更好地控制流量。