Java 不实现可克隆接口的对象克隆

Java 不实现可克隆接口的对象克隆,java,clone,Java,Clone,要克隆对象,我需要实现“可克隆”接口。因为这里我的类是一个jar文件(我指的是API)。所以我不能编辑这个类。我听说所有的类都是对基本对象类的扩展,这个对象类实现了可克隆的接口。这是否意味着我们可以在不实现接口的情况下直接克隆对象。如果是这样的话,在我的eclipse中,我没有克隆对象的任何选项是否有其他方法可以在不实现可克隆接口的情况下克隆对象。请解释一下 尝试对未实现可克隆性的类调用clone方法会引发CloneNotSupported异常,并且没有对象类未实现可克隆性 下面是来自对象类的c

要克隆对象,我需要实现“可克隆”接口。因为这里我的类是一个jar文件(我指的是API)。所以我不能编辑这个类。我听说所有的类都是对基本对象类的扩展,这个对象类实现了可克隆的接口。这是否意味着我们可以在不实现接口的情况下直接克隆对象。如果是这样的话,在我的eclipse中,我没有克隆对象的任何选项是否有其他方法可以在不实现可克隆接口的情况下克隆对象。请解释一下

尝试对未实现可克隆性的类调用clone方法会引发CloneNotSupported异常,并且没有对象类未实现可克隆性

下面是来自对象类的clone方法的javadoc

CloneNotSupportedException  if the object's class does not
 *               support the <code>Cloneable</code> interface. Subclasses
 *               that override the <code>clone</code> method can also
 *               throw this exception to indicate that an instance cannot
 *               be cloned.
此外,Object#clone方法受保护,因此您需要在类中实现clone方法,并将其公开,以便可以让生成类对象的类访问它,然后这些类可以调用clone。一个很好的例子是在ArrayList中实现克隆的方式

ArrayList实现了如下所示的可克隆性 公共类ArrayList扩展了AbstractList 实现列表、随机访问、可克隆、java.io.Serializable

然后实现克隆方法:

/**
 * Returns a shallow copy of this <tt>ArrayList</tt> instance.  (The
 * elements themselves are not copied.)
 *
 * @return a clone of this <tt>ArrayList</tt> instance
 */
public Object clone() {
try {
    ArrayList<E> v = (ArrayList<E>) super.clone();
    v.elementData = Arrays.copyOf(elementData, size);
    v.modCount = 0;
    return v;
} catch (CloneNotSupportedException e) {
    // this shouldn't happen, since we are Cloneable
    throw new InternalError();
}
}
/**
*返回此ArrayList实例的浅层副本。(修订)
*图元本身不会被复制。)
*
*@返回此ArrayList实例的克隆
*/
公共对象克隆(){
试一试{
ArrayList v=(ArrayList)super.clone();
v、 elementData=Arrays.copyOf(elementData,size);
v、 modCount=0;
返回v;
}捕获(CloneNotSupportedException e){
//这不应该发生,因为我们是可克隆的
抛出新的InternalError();
}
}

Java
对象
类不实现
可克隆接口。但是,它确实有
clone()
方法。但是此方法受
保护
,如果在未实现
可克隆
接口的对象上调用,则将抛出
CloneNotSupportedException
。因此,如果您无法修改要克隆的类,那么您就倒霉了,必须找到另一种方法来复制实例


但是应该注意的是,Java中的克隆系统充满漏洞,通常不再使用。2002年的Josh Bloch解释了其中的一些问题。查看这篇文章。

对象类中的clone()方法是受保护的,这意味着所有类都将使用受保护的访问修饰符继承它,因此如果您尝试在该类之外访问它而不克隆它,您将看不到它,如果您试图在不实现可克隆接口的情况下调用它,它也会抛出CloneNotSupportedException

如果您正在寻找一种创建克隆行为的方法,您需要在类中编写一个新方法,然后创建其中所有字段的副本,这基本上类似于创建对象现有状态的新副本

public class TestCloneable {
private String name = null;

/**
 * @param name the name to set
 */
public void setName(String name) {
    this.name = name;
}

/**
 * @return the name
 */
public String getName() {
    return name;
}


public TestCloneable createCopy(){
    TestCloneable testCloneable = new TestCloneable();
    testCloneable.setName(this.getName());
    return testCloneable;
}

}

无论如何,避免克隆通常是最佳做法,因为克隆很难正确执行()。也许这个类有一个复制构造函数

或者,如果它实现了Serializable或Externalizable,您可以通过将其写入字节流并读回内存来深度复制它

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(this);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
Object deepCopy = ois.readObject();

(来自)。这是快速和简单,但不漂亮。。。我一般认为这是最后的手段。

< P>他们是一个API,克隆对象不需要实现可克隆接口。 试试这个

此外,您还可以在此处找到有关克隆对象的更多详细信息


实现可克隆接口来克隆对象不是强制性的。
您可以在要克隆其对象的类中编写自己的克隆方法。

使用反射API您可以实现它。

您可以使用不安全来创建对象的实例,然后使用java反射将值复制到新实例中。但正如名字所说,这不是一个真正好的解决方案

public static Unsafe unsafe;
static {
    Field f;
    try {
        f = Unsafe.class.getDeclaredField("theUnsafe");
        f.setAccessible(true);
        unsafe = (Unsafe) f.get(null);
    } catch (NoSuchFieldException | IllegalAccessException e) {
        e.printStackTrace();
    }

}

public static <T> T clone(T object) throws InstantiationException {
    T instance = (T) unsafe.allocateInstance(object.getClass());
    copyInto(object,instance);
    return instance;
}

public static void copyInto(Object source,Object destination){
    Class<?> clazz = source.getClass();
    while (!clazz.equals(Object.class)) {
        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true);
            try {
                field.set(destination, field.get(source));
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        clazz = clazz.getSuperclass();
    }
}
公共静态不安全;
静止的{
字段f;
试一试{
f=不安全的.class.getDeclaredField(“不安全”);
f、 setAccessible(true);
不安全=(不安全)f.get(null);
}捕获(NoSuchFieldException | IllegalacessException e){
e、 printStackTrace();
}
}
公共静态T克隆(T对象)抛出实例化异常{
T instance=(T)unsafe.allocateInstance(object.getClass());
copyInto(对象、实例);
返回实例;
}
公共静态void copyInto(对象源、对象目标){
Class clazz=source.getClass();
而(!clazz.equals(Object.class)){
for(字段:clazz.getDeclaredFields()){
字段。setAccessible(true);
试一试{
set(destination,field.get(source));
}捕获(非法访问例外e){
e、 printStackTrace();
}
}
clazz=clazz.getSuperclass();
}
}

是否有其他方法可以在不实现可克隆接口的情况下克隆对象……感谢您的回复“但是应该注意,Java中的克隆系统充满漏洞,通常不再使用。”--您可以为语句添加引用吗?您可以使用构造函数创建一个新实例,并跨多个实例复制所需的状态。这种方法的可行性实际上取决于要复制的对象的类别。我在无法修改我要克隆的类的地方被完全卡住了。你能给我建议另一种克隆方法吗?为什么你觉得你必须这样做?您最好告诉我们您试图解决的总体问题,而不是您认为解决这个问题可能需要的编程步骤。换句话说,你可能做错了。根据答案中的评论,我认为OP需要一个复制构造函数。嗨,气垫船。我在这里清楚地解释我的问题。我有一个名为XYZ的类,还有一个返回thi对象的方法