作者:~小明学编程
文章专栏:JavaSE基础
格言:目之所及皆为回忆,心之所想皆为过往
目录
Cloneable接口
Java 中内置了一些很有用的接口, Clonable 就是其中之一,Object 类中存在一个 clone 方法, 调用这个方法可以创建一个对象的 "拷贝". 但是要想合法调用 clone 方法, 必须要先实现 Clonable 接口, 否则就会抛出 CloneNotSupportedException 异常。
下面给大家一个实例:
浅拷贝
定义:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。即对象的浅拷贝会对“主”对象进行拷贝,但不会复制主对象里面的对象。”里面的对象“会在原来的对象和它的副本之间共享。
class Person implements Cloneable{
public int age;
public void eat() {
System.out.println("eat()");
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class TestDome {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
person.age = 100;
Person person2 = (Person) person.clone();
System.out.println(person2);
}
}
这里我们是通过实现接口进行了一个浅拷贝。
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
person.age = 100;
Person person2 = (Person) person.clone();
person2.age = 10;
System.out.println(person);
System.out.println(person2);
}
我们这里对person2的age进行一个更改然后我们接着输出person和person2我们看到结果。
深拷贝
定义:深拷贝是一个整个独立的对象拷贝,深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。
class Money {
public int m = 88;
}
class Person implements Cloneable{
public int age;
public Money money = new Money();
public void eat() {
System.out.println("eat()");
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class TestDome {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
Person person2 = (Person) person.clone();
System.out.println(person.money.m);
System.out.println(person2.money.m);
System.out.println("----------------------");
person2.money.m = 99;
System.out.println(person.money.m);
System.out.println(person2.money.m);
}
}
这里我们看到我们打印的都是99,这是因为啥呢,我们前面所进行的拷贝只是单纯的一个拷贝,不会拷贝我们对象里面的对象所以我们person和person2都是公用同一个Money类的,要想解决这个问题我们就得对对象里面的对象也进行拷贝,这里就叫做我们的深拷贝。
class Money implements Cloneable{
public int m = 88;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Person implements Cloneable{
public int age;
public Money money = new Money();
public void eat() {
System.out.println("eat()");
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
Person tem = (Person) super.clone();
tem.money = (Money) this.money.clone();
return tem;
}
}
public class TestDome {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
Person person2 = (Person) person.clone();
System.out.println(person.money.m);
System.out.println(person2.money.m);
System.out.println("----------------------");
person2.money.m = 99;
System.out.println(person.money.m);
System.out.println(person2.money.m);
}
}
首先我们的Money类要实现一个cloneable的接口才能对我们当前的类进行一个拷贝,之后就是重写我们的clone方法.
protected Object clone() throws CloneNotSupportedException {
Person tem = (Person) super.clone();
tem.money = (Money) this.money.clone();
return tem;
}
首先定义一个临时的变量tem,并且将super.clone()强转为Person之后找到我们对象里面的Money对象再进行一个强转操作,最后进行返回。
这里我们就实现了深拷贝。