Java深层克隆—如果可以克隆,则克隆ArrayList中的每个元素,而不考虑类型

Java深层克隆—如果可以克隆,则克隆ArrayList中的每个元素,而不考虑类型,java,arraylist,casting,clone,Java,Arraylist,Casting,Clone,我有一个ArrayList a,它可以包含任何类型的对象。然后我需要遍历ArrayList的元素。如果元素实现了Cloneable,我需要克隆该元素(意思是复制它并在内存中给它自己的位置),然后将克隆的元素添加到ArrayList b中。问题在于铸造。我需要强制转换到正确的对象类型,然后调用clone()。(因为对象中的克隆()受保护。) 在下面的代码中,我用一堆if语句成功地实现了这一点。在每个元素上,我说if Cloneable,然后嵌套在if语句中,我有更多if语句,检查类型是否正确。当程

我有一个ArrayList a,它可以包含任何类型的对象。然后我需要遍历ArrayList的元素。如果元素实现了Cloneable,我需要克隆该元素(意思是复制它并在内存中给它自己的位置),然后将克隆的元素添加到ArrayList b中。问题在于铸造。我需要强制转换到正确的对象类型,然后调用clone()。(因为对象中的克隆()受保护。)

在下面的代码中,我用一堆if语句成功地实现了这一点。在每个元素上,我说if Cloneable,然后嵌套在if语句中,我有更多if语句,检查类型是否正确。当程序找到正确的类型时,它将强制转换和克隆。所有这些代码都可以工作,但我希望有一种方法可以在不使用这些if语句的情况下强制转换然后克隆(),因为可能有一些类我还不知道。有办法做到这一点吗?(我可以使用Class.cast()进行强制转换,但在此类转换中调用clone()尚未成功。)

我尝试序列化数组列表,实现自己的接口(使用clone()方法),并调用一个复制构造函数。这些都不适用于所有情况。就我所知,铸造和克隆是唯一可靠的方法,使其工作。如果有一种方法可以在不指定确切类的情况下强制转换和克隆,那么这种方法适用于所有情况。否则,我就被难倒了,需要另一个解决方案。(如果有一种方法可以循环遍历对象中的每个字段,而不考虑可访问性,那么这种方法也可能有效。)

这是我的密码:

// Establish variables
TestClass t = new TestClass();
TestClass u = new TestClass(1);
Point p = new Point();
Point q = new Point(1, 2);

// Set up ArrayList a
ArrayList a = new ArrayList();
a.add(t);
a.add(u);
a.add(p);
a.add(q);

// Get number of elements in a
int n = a.size();

// Set up ArrayList b
ArrayList b = new ArrayList();

// Clone all Cloneable elements from a into b
for (int i = 0; i < n; i++)
    if (a.get(i) instanceof Cloneable)
        if (a.get(i) instanceof TestClass)
            b.add(((TestClass)a.get(i)).clone());
        else if (a.get(i) instanceof Point)
            b.add(((Point)a.get(i)).clone());
    //ISSUE: I need to be able to cast and then clone based on the class a.get(i) represents, to avoid these if statements.

// Change initial variables. They change in ArrayList a (due to referencing the same memory) but not b
t.i = 2;
u.i = 3;
p.x = 3;
p.y = 4;
q.x = 5;
q.y = 6;

System.out.println(a);
System.out.println(b);
//建立变量
TestClass t=新的TestClass();
TestClass u=新的TestClass(1);
点p=新点();
点q=新点(1,2);
//设置ArrayList a
ArrayList a=新的ArrayList();
a、 加(t);
a、 加(u);
a、 加(p);
a、 加(q);
//获取一个文件中的元素数
int n=a.size();
//设置ArrayList b
ArrayList b=新的ArrayList();
//将所有可克隆元素从a克隆到b
对于(int i=0;i
TestClass和Point是我编写的类。它们实现可克隆


感谢您提供的任何帮助。

我认为您可以使用反射

if (a.get(i) instanceof Cloneable) {
  Cloneable c = (Cloneable) a.get(i);
  try {
    Method cloneMethod = c.getClass().getMethod("clone", new Class<?>[] {});
    cloneMethod.setAccessible(true);
    Object clone = cloneMethod.invoke(c, new Object[] {});
    b.add(clone);
  } catch (Exception e) {
    // Add real error handling.
    e.printStackTrace();
  }
} else {
  // It isn't cloneable.
}
if(a.get(i)可克隆实例){
可克隆c=(可克隆)a.get(i);
试一试{
方法cloneMethod=c.getClass().getMethod(“克隆”,新类[]{});
cloneMethod.setAccessible(true);
objectclone=cloneMethod.invoke(c,新对象[]{});
b、 添加(克隆);
}捕获(例外e){
//添加真正的错误处理。
e、 printStackTrace();
}
}否则{
//它是不可克隆的。
}

Java中的整个克隆机制基本上被破坏了。 例如,见

您可以使用一个具有所有功能的库(-(归功于Cojones)或创建自己的接口,如

public interface Copyable<T> {
 T copy();
}
或者,如果您只知道它是可复制的:

Copyable<?> copy = x.copy();
Copyable copy=x.copy();
但在大多数情况下,最好使用现有的解决方案,如上面的库


(编辑:最好不要使用Java自己的克隆工具:)

对不起,这不管用。我得到以下错误:找不到符号:方法clone()位置:interface java.lang.Cloneable b.add(c.clone());可能是因为clone()在Object中,而不是在Cloneable中?(Cloneable为空)每个Cloneable也是Object类型,克隆的对象版本也不可见。@user1567060已编辑以使用反射。如果不需要,我建议不要使用反射。这真的很容易出错,你可以找到更简单的方法来解决这个问题。看起来你的反思想法奏效了。我考虑过反思,但不是这样想的。在可克隆扩展对象上我信任您(因为我被告知所有对象都扩展对象),但c.clone()仍然不起作用。不过,看起来这个想法会奏效。我感谢您的帮助,并将在我将解决方案实施到实际项目中时通知您。(可能今天晚些时候)您是否正在尝试为实现您的深度克隆的任何类解决此问题?一般来说,以这种方式使用instanceof往往是一种代码味道。当一个新类出现后会发生什么?你应该重新考虑整体设计问题。我会尽快去图书馆看看。谢谢
Copyable<?> copy = x.copy();