自学内容网 自学内容网

Clonable接口和深拷贝

Clonable接口:

Java中也内置了一些很有用的接口,Clonable就是其中之一。

object类中存在一个Clone方法,调用这个方法可以创建一个对象的“拷贝”,但是想要合法使用Clone方法,必须要先实现Clonable接口,否则就会抛出CloneNotSupportedException 异常。

下面举一个例子:

我们定义一个Animal类,并实现Clonable类(这样才能实现“拷贝”的方法),并在Animal类中重写Clone方法:

public class Animal implements Cloneable{//一定要实现Clonable接口
    private String name;
     public Animal(String name){
         this.name=name;
     }
     public Object clone() throws CloneNotSupportedException{//重写父类的Clonable方法,返回值是父类类型
         Object clone = super.clone();
         return clone;
     }

    @Override
    public String toString() {//重写父类的toString方法
        return "Animal{" +
                "name='" + name + '\'' +
                '}';
    }
}

我们在idea中可以看到,Cloneable接口里面是一个空的

既然是空的,那为什么还要实现该接口呢?

其实Cloneable是一个标记接口,表示实现该接口的类是可以实现克隆方法的,如果实现就会报错。

在测试类中:

public class Test {
    public static void main(String[] args)
            throws CloneNotSupportedException{
     Animal a1=new Animal("毛毛");
     Animal a2=new Animal("无名氏");
        System.out.println("交换前"+a1.toString()+a2.toString());
        a2=(Animal) a1.clone();
        System.out.println("交换后"+a1.toString()+a2.toString());
    }
}

为什么在main方法后面,要抛出一个异常,因为在Animal类中Clone方法中,有一个异常的东西,需要即使处理。

为什么在克隆时, a2=(Animal) a1.clone();这里要进行强转呢?

因为Animal类中的Clone方法返回类型是object,需要转换成Animal类型

画图帮助理解一下:

 经过a2=(Animal) a1.clone()克隆后,会将a1的所指向的对象克隆一份出来,并将地址给到a2.

 但是,我再写一个AGE类用来表示动物的寿命。

class AGE{
    int age;
    AGE(int a){
        this.age=a;
    }
}
public class Animal implements Cloneable{//一定要实现Clonable接口
    private String name;
    AGE A=new AGE(10);//表示寿命
    public Animal(String name){
        this.name=name;
    }
    public Object clone() throws CloneNotSupportedException{//重写父类的Clonable方法,返回值是父类类型
        Object clone = super.clone();
        return clone;
    }

    @Override
    public String toString() {//重写父类的toString方法
        return "Animal{" +
                "name='" + name + '\'' +"age="+ A.age+
                '}';
    }
}

在测试类中

public class Test2 {
    public static void main(String[] args) throws CloneNotSupportedException {
        Animal a1=new Animal("猫猫");
        Animal a2=(Animal) a1.clone();
        System.out.println(a1.toString());
        System.out.println(a2.toString());
        a1.A.age=12;//修改动物1的寿命
        System.out.println(a1.toString());
        System.out.println(a2.toString());
    }
}

输出结果:

观察其实我们只对a1的进行修改了寿命,但打印出来我们会发现a2的寿命也变了。上面的拷贝只是浅拷贝,虽然a2是a1的克隆体,但是a2也是一个单独的个体,我们只需要修改a1的age,不希望a2的age也修改。

只克隆了Animal对象,没有克隆AGE对象。这里的现象我们称为:浅拷贝

深拷贝:

什么叫深拷贝呢?------->将上面的AGE重新拷贝一份,就叫做深拷贝。

那么如何进行深拷贝:

1.首先,我们可以想到将AGE类中实现一个拷贝方法。

class AGE implements Cloneable{
    int age;
    AGE(int a){
        this.age=a;
    }
    public Object clone() throws CloneNotSupportedException{//重写父类的Clonable方法,返回值是父类类型
        Object clone = super.clone();
        return clone;
    }
}

再在Animal类的Clone方法改一改:

public Object clone() throws CloneNotSupportedException{//重写父类的Clonable方法,返回值是父类类型
       Animal tmp = (Animal) super.clone();//先将Animal进行克隆
        tmp.A=(AGE)this.A.clone();//然后将AGE寿命进行克隆
        return tmp;
    }

最后运行结果:


原文地址:https://blog.csdn.net/2301_80235470/article/details/142041749

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!