如何在通用 class [Java] 中正确实现对 clone() 的调用

How to properly implement the call to clone() in a generic class [Java]

我有一个通用接口,我必须创建一个 class 来实现它。起初我认为这会工作得很好,把它放在接口需要一个实现克隆方法的 class 的文档中

genericClass<E extends Cloneable> implements genericInterface<E extends Cloneable>{
E data;

//code

public E get(){
return this.data.clone()
}
}

然而这在实践中行不通

package securedatacontainer;

public class Demo {


    public static void main(String[] args) throws CloneNotSupportedException {

        String s = "user";
        A a = new A(5, s);
        A b = a.clone();
        System.out.println("a equals b: " +(a.equals(b)));
        System.out.println("a == b: " + (a == b));


        B<A> c = new B<>(a);
        System.out.println("a equals c.data: " +(a.equals(c.data)));
        System.out.println("a == c.data: " + (a == c.data));

        A k = c.get();
        System.out.println(k.value);

    }

}


class A implements Cloneable{
    int value;
    String name;


    public A(int x, String str ){
        this.value = x;
        this.name  = str;
    }

    @Override
    public A clone() throws CloneNotSupportedException {
    A temp = new A(this.value, this.name);
    return temp;
    }


    public boolean equals(A elem){
        return (this.name).equals(elem.name) && this.value==elem.value;
    }
}




class B <E extends Cloneable>{
    E data;

    public B(E elem){
        this.data=elem;
    }

    public E get() throws CloneNotSupportedException{
        return (E) this.data.clone();
    }


}

我明白了

Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - Erroneous sym type: java.lang.Cloneable.clone
    at securedatacontainer.B.get(Demo.java:60)
    at securedatacontainer.Demo.main(Demo.java:19)

因为该项目应该是一个数据存储,我真的怀疑我的老师想要一些通用 E 元素的浅拷贝(请注意,这只是一个简单的克隆测试程序,而不是实际项目)。任何人都可以告诉我为什么这不起作用或我如何让它起作用?我不能对输入 E 元素做任何假设,只是它有自己的 clone() 方法

因为 clone 方法在 Object class 上被标记为 protected,所以一般不能在任意对象上调用此方法。 clone() 方法背后的想法是支持它的 classes 将覆盖该方法,将其声明为 public.

此处保留全部功能的唯一真正解决方案是使用反射来访问该方法并绕过访问修饰符。

这是我的解决方案,

public class B<E extends Cloneable> {
    E data;

    public B(E elem) {
        this.data = elem;
    }

    @SuppressWarnings("unchecked")
    public E get() {
        Method clone = null;
        try {
            clone = data.getClass().getMethod("clone");
            Object[] args = new Object[0];
            return (E) clone.invoke(data, args);
        } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException
                | InvocationTargetException e) {
            throw new RuntimeException(e);
        }

    }
}

Clonable 确定对象的受保护克隆实现的行为:如果 class 实现 Cloneable,对象的克隆方法 returns目的;否则它会抛出 CloneNotSupportedException。但是您在 class A 中实现克隆方法的方式没有调用 Object's clone 方法,所以这没有效果。

@Override
public A clone() throws CloneNotSupportedException {
    A temp = new A(this.value, this.name);
    return temp;
} 

如果你想使用那个工具,你必须像这样实现它,

public class A implements Cloneable {
    int value;
    String name;

    public A(int x, String str) {
        this.value = x;
        this.name = str;
    }

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

    public boolean equals(A elem) {
        return (this.name).equals(elem.name) && this.value == elem.value;
    }
}

在这种情况下,如果您的 class A 没有实现 Cloneable,那么 java.lang.CloneNotSupportedException 将被抛出。

最后,如果您尝试将未实现 Cloneable 的内容传递给 Demo 中的 B 构造函数,声明 public class B<E extends Cloneable> 会给您一个编译器错误=48=].

B<A> c = new B<>(doesNotImplCloneable);   // Gives a compilation error.

因此,如果您正在使用我在此处显示的对象的克隆方法,则 extends/implements Cloneable 是可行的方法。