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)!