目录
一,浅拷贝
拷贝就是复制粘贴,简单来说就是将对象中的内容"复制粘贴"到另一个对象中,使其中的成员内容相同,而浅拷贝就是只拷贝一层(现在可能看不懂,等看完深拷贝就懂了)
那么怎样实现浅拷贝呢?在Java 中有一个内置的 Clonable 接口,在Object 类中也存在一个 clone 方法,调用这个方法可以创建一个对象的 "拷贝"。举一个例子:
class Person {
public int age;
public Person(int age) {
this.age = age;
}
}
public class Test {
public static void main(String[] args) {
Person person1 = new Person(10);
Person person2 = person1.clone();
}
}
1.1 protected访问控制异常
但是它报错了,我们一个一个解决,先解决第一个,clone方法在Object类中是这样的:
该方法是被访问修饰限定符protected修饰的,所有它只能在同一个包中或不同包的子类中使用,而我们知道Person类和Object类在不同的包中,因此要拷贝Person类就必须在Person类中重写clone方法,例如:
class Person {
public int age;
public Person(int age) {
this.age = age;
}
//重写
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
1.2 不兼容问题
我们来解决第二个问题 - 不兼容,因为我们调用clone方法的返回值是 Object 类,而我们要将它赋值给一个Person类对象,所以我们要使用强制类型转换,将Object类强转成Person类,例如:
public class Test {
public static void main(String[] args) {
Person person1 = new Person(10);
Person person2 = (Person) person1.clone();
}
}
1.3 受查异常/编译时异常
但是当我们运行时,它又抛出了如下异常:
该异常叫受查异常/编译时异常,必须是编译时处理,按以下步骤处理:
1. 把鼠标放到clone();上:
2. 按 Alt + Enter 键,点击用红框框出来的
3. 它会自动补上以下内容
1.4 不支持异常
处理完以上问题后,它有报错了:
该问题的意思就是Person类不支持clone,我们要给它实现开头讲到的Cloneable接口,例如:
//实现Cloneable接口
class Person implements Cloneable{
public int age;
public Person(int age) {
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Person person1 = new Person(10);
Person person2 = (Person) person1.clone();
}
}
最后画个图来理解一下:
二,深拷贝
深拷贝的功能比浅拷贝更强,能够实现"多层"拷贝,举一个例子(除了新增了一个Money类,其他与上面相同):
//新增
class Money{
public int money = 3;
}
class Person implements Cloneable{
public int age;
//新增
public Money money = new Money();
public Person(int age) {
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Person person1 = new Person(10);
Person person2 = (Person) person1.clone();
}
}
这是以上代码的实现所得图:
我们要的深拷贝实现的图:
如何代码实现:
class Money implements Cloneable{
public int num = 3;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Person implements Cloneable{
public int age;
public Money money = new Money();
public Person(int age) {
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Person tmp = (Person) super.clone();//浅拷贝 - 克隆Person类的成员
tmp.money = (Money) this.money.clone();//拷贝Money类的成员
return tmp;
}
//这是为了输出,与拷贝无关
@Override
public String toString() {
return "Person{" +
"age=" + age +
", money=" + money.num +
'}';
}
}
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Person person1 = new Person(10);
Person person2 = (Person) person1.clone();
System.out.println(person2);
System.out.println(person1);
}
}
与浅拷贝的实现大同小异,多了一步Money类的拷贝 - 实际上就是实现了两次浅拷贝!