我正在尝试实现我自己的这个对象的深层副本:
public class Column<T extends Cloneable>
{
private final ArrayList<T> values;
private String name;
// ...
}
这就是克隆这个类的实例的方法:
Column<String> column = new Column<String>();
// ...
Column<String> columnCopy = column.copy();
这是我正在尝试实现的方法(假设方法clone()是正确的ovverridden):
public Column<T> copy()
{
ArrayList<T> valuesCopy = new ArrayList<T>();
for (T value : values)
valuesCopy.add(value.clone()); // The method clone() from the type Object is not visible
return new Column<T>(name, valuesCopy);
}
如果值类型为T,定义为T extends Cloneable
,为什么方法clone()不可见?
感谢。
答案 0 :(得分:5)
由于以下原因,您的代码无法看到clone
方法。
clone
方法为protected
in Object
。Cloneable
interface是一个标记界面,不保证public
clone
方法(或任何方法)的存在。T
的泛型类型参数Cloneable
,但在类型擦除之后,这只变为Cloneable
,因此编译器只能假定Object
方法存在,clone
受到保护,因此无法以这种方式调用。答案 1 :(得分:1)
Cloneable中没有clone()。
请注意,此接口不包含克隆 方法。因此,仅仅通过克隆对象是不可能的 因为它实现了这个接口。即使是 克隆方法是反射性调用的,不能保证它 会成功的。
答案 2 :(得分:1)
clone
方法由于其他原因而有几个原因不起作用。
有几种方法可以自己执行深层复制,或者通过逐字迭代对象并将每个元素复制到“克隆”对象的新元素中,或者更快捷的方法是serialize
对象然后deserialize
它...因为这将做一个精确的深层复制。
这是一个快速示例,它接受任何对象并返回完全重复的对象。确保你回到预期的类型。
public static Object makeClone(final Object obj)
throws IOException, ClassNotFoundException {
java.io.ByteArrayOutputStream bos = new java.io.ByteArrayOutputStream();
java.io.ObjectOutputStream obj_out = new java.io.ObjectOutputStream(bos);
obj_out.writeObject(obj);
java.io.ByteArrayInputStream bis =
new java.io.ByteArrayInputStream(bos.toByteArray());
java.io.ObjectInputStream obj_in = new java.io.ObjectInputStream(bis);
@SuppressWarnings("unchecked")
Object newObj = obj_in.readObject();
bos.close();
bis.close();
obj_out.close();
obj_in.close();
return newObj;
}
答案 3 :(得分:0)
对不起,我确信Cloneable
界面不仅仅是一个标记界面。
您如何看待我自己的解决方案? (我不确定它是否正确)
public class Column<T extends Copyable<T>> implements Cloneable
{
private final ArrayList<T> values;
private String name;
// ...
public Column<T> clone()
{
ArrayList<T> valuesCopy = new ArrayList<T>();
for (T value : values)
valuesCopy.add(value.clone());
return new Column<T>(name, valuesCopy);
}
}
public interface Copyable<T> extends Cloneable
{
public T clone();
}