CloneNotSupportedException的解决方案 + Object的clone方法分析

发布时间:2023年12月31日

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 对象,也就是对象描述的指针(指向对象的首地址)

文章来源:https://blog.csdn.net/qq_43985303/article/details/135315353
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。