、对象的克隆
1、为什么需要克隆?
对于基本数据类型,可以将值直接复制给另一个变量,这里两个变量相互独立,而引用数据类型(自定义类) 对于引用类型的赋值并没有产生新的个体,而是将两个变量的类型指向同一个对象。 (本质只有一个对象),如果想要赋值的对象与原始对象独立,则需要进行“对象克隆”
2、如何克隆
我们知道任意一个类都继承自Object类,其中Object类提供一个clone方法 用于克隆对象。
实现步骤:
a、 实现 接口 Cloneable
b、重写 clone方法(由于该方法是Object的 protectect修饰 不能直接访问)
3、浅克隆和深克隆
3.1、浅克隆
在浅克隆中,如果原型对象的成员变量是值类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。
Java的对象克隆默认是浅克隆,
3.2、深克隆
在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。
简单来说,在深克隆中,除了对象本身被复制外,对象所包含的所有成员变量也将复制
实现深克隆的方式:
1、需要将克隆对象的引用数据类型 也实现克隆
public class Student implements Cloneable {
private int id;
private String sname;
private int age;
//收货地址
private Address address;
//实现深克隆
@Override
protected Object clone() throws CloneNotSupportedException {
// return super.clone();
Student stu = (Student)super.clone();
// 获取学生的address
Address address = (Address) stu.getAddress().clone();
// 将address对象放入 新克隆的stu中
stu.setAddress(address);
return stu;
}
}
public class Address implements Cloneable{
//联系人
private String contectName;
//联系电话
private String contectPhone;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
测试:
public static void main(String[] args) throws CloneNotSupportedException {
// 创建学生对象
Student stu1 = new Student(1001,"张三",22);
Address address = new Address("马创的女朋友","18888888888");
// 将收货地址 与该学生对象关联
stu1.setAddress(address);
//克隆一个对象
Student stu2 = (Student)stu1.clone();
System.out.println(stu1.getId()+"---"+stu1.getSname());
System.out.println(stu2.getId()+"---"+stu2.getSname());
// 问题:是否会克隆新的address对象 还是说address的内存地址相同
System.out.println(stu1.getAddress());
System.out.println(stu2.getAddress());
// 对于克隆对象的引用数据类型,它默认不会创建引用数据类型的 新对象
// 这种方式称为“浅克隆”
// Java也可以实现深克隆
System.out.println(stu1.getAddress().getContectName());
System.out.println(stu2.getAddress().getContectName());
}