Clonable接口和深拷贝\浅拷贝
拷贝原理
class Person implements Cloneable{
public int age = 2;
@Override
protected Object clone() throws CloneNotSupportedException {
//要想完成克隆,必须调用Object,重写clone()方法
return super.clone();
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
}
public class Test1 {
public static void main(String[] args) throws CloneNotSupportedException {
Person person1 = new Person();
Person person2 = (Person)person1.clone();//向下转型
System.out.println(person1.age);
System.out.println(person2.age);
}
运行结果:
2
2
问题:clone方法是Object的方法,所以类都是继承Object的,为什么还要重写克隆方法呢?
我们去看克隆源码发现,克隆是C++代码实现的Object类中的方法.在源代码中Object的访问修饰符是protected修饰的,所以可以得出它们不是在同一包当中.确实可以通过super访问到.但是没有重写克隆方法和传入要克隆的地址.所以代码报错
class Person implements Cloneable{
public int age = 2;
// @Override
// protected Object clone() throws CloneNotSupportedException {
// //要想完成克隆,必须调用Object,重写clone()方法
// return super.clone();
// }
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
}
public class Test1 {
public void func() throws CloneNotSupportedException {
Person person1 = new Person();
Person person2 = (Person)super.clone();
System.out.println(person1);
System.out.println(person2);
}
public static void main(String[] args) throws CloneNotSupportedException {
Test1 test = new Test1();
test.func();
}
}
浅拷贝
package com.cou;
class Name implements Cloneable{
public String name = "张三";
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Person implements Cloneable{
public int age = 2;
public Name names = new Name();
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Test1 {
public static void main(String[] args) throws CloneNotSupportedException {
Person person1 = new Person();
Person person2 = (Person)person1.clone();//向下转型
System.out.println("person1年龄深拷贝前" + person1.age);
System.out.println("person2年龄深拷贝前" + person2.age);
person2.age = 23;
System.out.println("person1年龄深拷贝后" +person1.age);
System.out.println("person1年龄深拷贝后" +person2.age);
System.out.println("名字是深拷贝");
System.out.println("person1名字浅拷贝前" + person1.names.name);
System.out.println("person2名字浅拷贝前" + person2.names.name);
person2.names.name = "王五";
System.out.println("person1名字浅拷贝后" + person1.names.name);
System.out.println("person2名字浅拷贝后" + person2.names.name);
}
}
深拷贝
package com.cou;
class Name implements Cloneable{
public String name = "张三";
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Person implements Cloneable{
public int age = 2;
public Name names = new Name();
@Override
protected Object clone() throws CloneNotSupportedException {
//深拷贝
Person tmp = (Person) super.clone();
tmp.names = (Name) this.names.clone();
return tmp;
}
}
public class Test1 {
public static void main(String[] args) throws CloneNotSupportedException {
Person person1 = new Person();
Person person2 = (Person)person1.clone();//向下转型
System.out.println("person1年龄深拷贝前" + person1.age);
System.out.println("person2年龄深拷贝前" + person2.age);
person2.age = 23;
System.out.println("person1年龄深拷贝后" +person1.age);
System.out.println("person1年龄深拷贝后" +person2.age);
System.out.println("名字是深拷贝");
System.out.println("person1名字深拷贝前" + person1.names.name);
System.out.println("person2名字深拷贝前" + person2.names.name);
person2.names.name = "王五";
System.out.println("person1名字深拷贝后" + person1.names.name);
System.out.println("person2名字深拷贝后" + person2.names.name);
}
}
总结:深拷贝和浅拷贝,不是哪个方法决定的,而是看你自己的代码来决定实现的.