目录
1、Clonable 接口
- Java 中内置了一些很有用的接口, Clonable 就是其中之一;
- Object 类中存在一个 clone 方法,调用这个方法可以创建一个对象的 "拷贝",但是要想合法调用 clone 方法,必须要先实现 Clonable 接口,否则就会抛出 CloneNotSupportedException 异常。
- 代码如下:
class Person implements Cloneable{
public int age=20;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
}
public class Test {
public static void main(String[] args) throws CloneNotSupportedException{
Person person = new Person();
Person person1= (Person) person.clone();
//person1.age = 99;
}
}
1、这个类实现Cloneable这个接口,这个接口中是没有抽象方法的,所以叫做空接口,这里只证明Person这个类是可以被克隆的没有<>,不用传入类型。
2、如果想要克隆对象,要重写clone方法,他的父类是Object类,所以用super可以调用,generate生成或者crl+o可以自动生成,不用改变。
3、
- 建立一个Pesron的对象person,想要克隆person这个对象中的内容(也就是建立一个age的副本一样)
- 这时候Person这个类中就有clone方法了,可以直接用对象.调用,因为clone方法返回是Object类型,我们要Person类型,所以用强制类型转换。
2、浅拷贝
以下的深拷贝和浅拷贝的讨论都基于以下的代码,创建:
class Money implements Cloneable {
public double money=19.9;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Person implements Cloneable{
public int age=10;
public Money m = new Money();
//浅拷贝的重写
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
}
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
Person person2 = (Person) person.clone();
System.out.println(person.m.money);
System.out.println(person2.m.money);
person.m.money = 90.0;
System.out.println(person.m.money);
System.out.println(person2.m.money);
}
}
1、建立了一个person2 克隆了一个person中的对象,但是对象中引用m所指向的对象money没有被拷贝,也就是两个m指向了同一个空间。
(2)这时候我们改动一个person.m.money的值,两个对象中的money都改变了,这就是浅拷贝
浅拷贝:拷贝了对象,但是没有拷贝对象中引用m所指向的对象money。
3、深拷贝
- 我们想实现的是,不光拷贝了person中的对象,也将m所指向的对象money也拷贝了一份,并将新的地址赋给m。
- 这时改变person2.m.money的值,person中的money的值不会改变。
1、实现代码:
class Money implements Cloneable {
public double money=19.9;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Person implements Cloneable{
public int age=10;
public Money m = new Money();
//深拷贝的重写
@Override
protected Object clone() throws CloneNotSupportedException {
Person tmp =(Person) super.clone();
tmp.m = (Money) this.m.clone();
return tmp;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
}
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
Person person2 = (Person) person.clone();
System.out.println(person.m.money);
System.out.println(person2.m.money);
person.m.money = 90.0;
System.out.println(person.m.money);
System.out.println(person2.m.money);
}
}
2、对于Money这个类的克隆方法需要重写,目的是可以克隆money这个对象,记得Money这个类要实现Cloneable这个接口。
2、在Person中:
- 首先第一行是克隆一份person就是age和m,给到tmp变量;
- 第二行是克隆一份money,并将money的地址返回给tmp中的m(tmp我们是临时变量);
- 第三行是返回tmp的值,这里面是person2来接收了,并且tmp这个局部变量会销毁。
3、深拷贝中,因为money也被拷贝了一份,而且地址和person中的地址不同,所以我们改变person2中money的值,不会影响到person中money的值,这就是深拷贝。