为了账号安全,请及时绑定邮箱和手机立即绑定

如何在泛型类中正确实现对 clone() 的调用 [Java]

如何在泛型类中正确实现对 clone() 的调用 [Java]

蓝山帝景 2022-01-12 16:08:45
我有一个通用接口,我必须创建一个类来实现它。起初我认为这会很好,将它放在文档中,接口需要一个实现克隆方法的类genericClass<E extends Cloneable> implements genericInterface<E extends Cloneable>{E data;//codepublic 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() 方法
查看完整描述

1 回答

?
天涯尽头无女友

TA贡献1831条经验 获得超9个赞

因为该clone方法被标记为protected在Object类上,所以通常不能在任意对象上调用此方法。该clone()方法背后的想法是支持它的类将覆盖该方法,将其声明为公共的。


这里唯一保留完整功能的真正解决方案是使用反射来访问方法并绕过访问修饰符。


所以这是我的解决方案,


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确定 Object 的受保护克隆实现的行为:如果类实现了Cloneable,则 Object 的 clone 方法返回对象的逐字段副本;否则它会抛出CloneNotSupportedException. 但是您在类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;

    }

}

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


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


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

因此,如果您正在使用我在这里展示的对象的克隆方法,那么这extends/implements Cloneable就是要走的路。


查看完整回答
反对 回复 2022-01-12
  • 1 回答
  • 0 关注
  • 422 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号