现在有一个我们自定义的Person对象,如何去克隆这个对象?
class Person{
public int id;
@Override
public String toString() {
return "Person{" +
"id=" + id +
'}';
}
}
public class Test2 {
public static void main(String[] args) {
Person person1 = new Person();
}
}
1.给自定义的Person类实现Cloneable接口
class Person implements Cloneable{
public int id;
@Override
public String toString() {
return "Person{" +
"id=" + id +
'}';
}
}
2.重写Object克隆方法
class Person implements Cloneable{
public int id;
@Override
public String toString() {
return "Person{" +
"id=" + id +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
3. 声明异常,再进行强制类型转换
public class Test2 {
public static void main(String[] args) throws CloneNotSupportedException {
Person person1 = new Person();
Person person2 = (Person) person1.clone();
}
}
clone方法的返回值是Object,因此需要强制类型转换一下
浅拷贝
现在给这个 这个Person对象再添加一个NameAndMoney属性
class NameAndMoney{
String name;
double m;
public NameAndMoney(String name, double m) {
this.name = name;
this.m = m;
}
@Override
public String toString() {
return "NameAndMoney{" +
"name='" + name + '\'' +
", m=" + m +
'}';
}
}
class Person implements Cloneable{
public int id;
public NameAndMoney nameAndMoney;
public Person(int id, String name,double m) {
this.id = id;
this.nameAndMoney = new NameAndMoney(name,m);
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", nameAndMoney=" + nameAndMoney +
'}';
}
}
浅拷贝:直接使用克隆方法
public class Test2 {
public static void main(String[] args) throws CloneNotSupportedException {
Person person1 = new Person(1,"张三",9999);
Person person2 = (Person) person1.clone();
person2.id=2;
person2.nameAndMoney.name="李四";
person2.nameAndMoney.m=8888;
System.out.println(person1);
System.out.println(person2);
}
}
可以发现person2的改变会引起person1的变化,这就是浅拷贝,它只是把person1里面的内容完全复制了
也就是说只要0x11这个引用里面的内容发生改变,person1和person2都会发生改变
深拷贝
给NameAndMoney同样实现Cloneable接口,重写clone方法,再重写我们Person中的clone方法
class NameAndMoney implements Cloneable{
String name;
double m;
public NameAndMoney(String name, double m) {
this.name = name;
this.m = m;
}
@Override
public String toString() {
return "NameAndMoney{" +
"name='" + name + '\'' +
", m=" + m +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Person implements Cloneable{
public int id;
public NameAndMoney nameAndMoney;
public Person(int id, String name,double m) {
this.id = id;
this.nameAndMoney = new NameAndMoney(name,m);
}
@Override
protected Object clone() throws CloneNotSupportedException {
Person tmp = (Person) super.clone();
tmp.nameAndMoney = (NameAndMoney)this.nameAndMoney.clone();
return tmp;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", nameAndMoney=" + nameAndMoney +
'}';
}
}
关键代码
@Override
protected Object clone() throws CloneNotSupportedException {
Person tmp = (Person) super.clone();
tmp.nameAndMoney = (NameAndMoney)this.nameAndMoney.clone();
return tmp;
}
总结:
现在有a,b俩个对象,浅拷贝就相当于,b把a的内容完全复制,并赋予它新的地址,虽然这俩个引用的地址不同,但内容一样,如果这里面的内容有其他的引用,那此时a和b就共用了一个引用了,如果这个引用里面的内容发生修改,a和b都会发生改变.
可以把引用想象成一个壳子,b把a的壳子里面的内容复制到另一个壳子中,假如这个壳子里面包含了其它壳子,那么此时a和b就共用了这个它们共用的壳子,如果a或者b的任意一个改变了这个壳子里面的内容,此时a和b都会发生改变
深拷贝,就是b不是把a的内容完全复制,而是找出a里面还有哪些引用,并把这些引用的内容复制且赋予它们新的地址,这样a和b就不会有关联了
b不是把a里面的内容完全复制,而是找出a中还有哪些壳子,并把这些壳子里面的内容复制,然后给与这些壳子新的地址,这样a和b就不会指向同一个壳子了,有共用的壳子了