CloneNotSupportedException的解决方案 + Object的clone方法分析
CloneNotSupportedException的解决方案
引入问题:
在一次测试clone方法时,D类Override了Object类的clone方法
public class D {
    private Integer A1;
    private Integer A2;
    public D() {
    }
    public D(Integer a1, Integer a2 {
        A1 = a1;
        A2 = a2;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
123456789101112131415161718
在测试类中执行clone方法报错了
public class Test5 {
    public static void main(String[] args) {
        D p  = new D();
        D p2 = null;
        try {
            p2 = (D)p.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        System.out.println(p == p2);
    }
}
12345678910111213141516

抛出了 CloneNotSupportedException
寻找原因:
既然是重写自Object的clone方法,那么去看看Object对该方法的定义:
protected native Object clone() throws CloneNotSupportedException;
1
其中对于异常抛出的描述如下:
Throws:
 CloneNotSupportedException – if the object’s class does not support the Cloneable interface. Subclasses that override the clone method can also throw this exception to indicate that an instance cannot be cloned.
如果对象的class不实现Cloneable接口,子类重写clone方法会同样抛出异常表示实例不能被克隆;
哦?
那不意思就是说:你要不父类实现Cloneable接口,要不就子类实现Cloneable
两个测试代码:
测试1: 在父类上实现Cloneable接口
public class TestClone {
    public static void main(String[] args) throws CloneNotSupportedException {
        Father father = new Father();
        Father fatherClone = (Father) father.clone();
        Son son = new Son();
        Son sonClone = (Son) son.clone();
        System.out.println(father==fatherClone);
        System.out.println(son==sonClone);
    }
}
class Father implements Cloneable{
    private Integer f1;
    private Integer f2;
    public Father() {
    }
    public Father(Integer f1, Integer f2) {
        this.f1 = f1;
        this.f2 = f2;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Son extends Father{
    private Integer s1;
    private Integer s2;
    public Son() {
    }
    public Son(Integer s1, Integer s2) {
        this.s1 = s1;
        this.s2 = s2;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
不出意外,没有任何问题

测试2:在子类上实现Cloneable接口
public class TestClone {
    public static void main(String[] args) throws CloneNotSupportedException {
//        Father father = new Father();
//        Father fatherClone = (Father) father.clone();
        Son son = new Son();
        Son sonClone = (Son) son.clone();
//        System.out.println(father==fatherClone);
        System.out.println(son==sonClone);
    }
}
class Father {
    private Integer f1;
    private Integer f2;
    public Father() {
    }
    public Father(Integer f1, Integer f2) {
        this.f1 = f1;
        this.f2 = f2;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Son extends Father implements Cloneable{
    private Integer s1;
    private Integer s2;
    public Son() {
    }
    public Son(Integer s1, Integer s2) {
        this.s1 = s1;
        this.s2 = s2;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
执行父类的clone报错,但是执行子类的clone没得问题

SO:
哪个类的需要clone,就在那个类在重写clone方法,并且在那个类或者其父类中实现Cloneable接口
详细分析clone方法的实现:
由于Object的clone方法是native修饰的,也就是虚拟机内部实现的方法
根据Hotspot虚拟机定义,找到Object.c

为什么要实现Cloneable接口?
在JVM_Clone方法中有这样一段判断:

很明显,虚拟机给你抛出的异常
为什么会出现地址不同的情况?

很明显,直接在堆内存中执行allocate方法开辟新的对象空间
并返回一个 oop 对象,也就是对象描述的指针(指向对象的首地址)
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!