如何说服编译器一个Object是可克隆的(java)



我想克隆一个给定的对象。

如果我做这个

public class Something{
    Object o; //set in the constructor
    public Something(Object o){
         this.o = o;}
    public Something clone() throws CloneNotSupportedException{
         Something temp = super.clone();
         if (o instanceof Cloneable) //important part
             temp.o = o.clone(); //important part
         else temp.o = o;
    }
}

这将不起作用,因为o.clone()受到保护。

如果我改为

         if (o instanceof Cloneable) //important part
             temp.o = ((Cloneable)o).clone(); //important part

它也不起作用,因为Cloneable是一个空接口。

那么,我该如何让编译器相信你可以克隆o呢?

如果可以实现Serializable接口,则可以使用序列化。当然,不利的一面是表现。

https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/SerializationUtils.html#clone(java.io.Serializable)

如果你不想使用apachecommons,你可以使用ObjectOutputStream/ObjectInputStream做同样的事情。

您不能,在实现clone()时,必须知道什么是克隆,必须知道实现类。

克隆的另一种选择是使用复制构造函数,这也有同样的问题,你必须知道类。

有人说不要使用克隆,也有人说定义自己的接口,例如:Copyablehttp://c2.com/cgi/wiki?CloneableDoesNotImplementClone

您可以使用反射

//We need reflection
import java.lang.reflect.*;
    //This class is the backbone of the feature
    public class MyCloneable implements Cloneable {
        //A constructor. For the sake of simplicity, the constructor is an empty constructor.
        public MyCloneable() {}
        //We implement the clone method. This returns a clone
        protected Object clone() throws CloneNotSupportedException {
            //We need the class of the object
            class c = this.getClass();
            //We get the empty constructor of the object
            Constructor constructor = c.getConstructor(new Class[]{});
            //newClone will be the cloned object
            Object newClone = constructor.newInstance(new Object[]{});
            //We get the array of fields
            Field[] fields = c.getDeclaredFields();
            //We iterate the fields to copy them. You might want to close these too, but for the sake of simplicity I did not tackle with this issue
            for (int fieldIndex = 0; fieldIndex < fields.length; fieldIndex++) {
                //We copy the field values of this into the clone
                fields[fieldIndex].set(newClone, fields[fieldIndex].get(this));
            }
            //newClone is ready and kicking
            return newClone;
        }
        //We need this method to be able to reach the clone method publicly
        public Object runClone() throws CloneNotSupportedException {
            return this.clone();
        }
    }

此代码未经测试,欢迎任何意见。

您需要使用从MyCloneable继承的类的对象。

在Java中没有克隆对象的通用方法。类型必须在其公共API中提供要克隆的方法(可以称为clone()或其他方法;无关紧要),并且Java中没有此类类型的公共超类型。

java.lang.Cloneable接口必须由我们要创建其对象克隆的类实现。如果我们不实现可克隆接口,clone()方法将生成CloneNotSupportedException

clone()方法是在Object类中定义的。clone()方法的语法如下:

protected Object clone() throws CloneNotSupportedException

所以你的课应该是

public class Something implements Cloneable {
    private Object o; //set in the constructor
    public Something(Object o) {
        this.o = o;
    }
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    public Object getObject() {
        return o;
    }
    public static void main(String[] args) {
        Something s = new Something("try");
        System.out.println(s.getObject());
        try {
            Something s2 = (Something) s.clone();
            System.out.println(s2.getObject());
        } catch (CloneNotSupportedException ex) {
            Logger.getLogger(Something.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

最新更新