对象克隆又称为对象复制,从一个对象克隆出另一个新对象,新对象的属性值和原来相同。相当于new一个对象,然后将属性一个个赋给新对象,只不过我们可以使用clone方法来取代这个过程。根据克隆深度的不同,分为如下
克隆实现分为三步
1. 需要克隆的对象实现Cloneable接口,Cloneable只是一个标志,没有任何需要实现的方法 2. 在该对象中重写父类的clone方法 2. 在clone方法中调用super.clone(),实际是调用Object中的clone方法
1. 浅层复制
浅层复制指只克隆对象的基本类型属性,而不克隆引用类型属性。比如一个User对象中有一个属性为Student对象类型,那么复制后,新对象的student属性的引用和原对象student的属性引用相同,修改student的属性会互相影响。
为压缩不必要的代码,下面属性访问权限直接使用public来处理
// Student类 class Student{ public String stuName; } // User类,实现Cloneable接口 class User implements Cloneable{ public int id; public Student stu; public User(int id, Student stu) { this.id = id; this.stu = stu; } // 重写clone方法 @Override protected User clone() throws CloneNotSupportedException { return (User) super.clone();// 调用Object中的clone方法 } } //测试类 public class Test { public static void main(String[] args) throws CloneNotSupportedException { Student stu = new Student(); stu.stuName = "测试"; User u1 = new User(1, stu); // 克隆 User u2 = (User) u1.clone(); // 修改u1中stu的属性stuName为1 u1.stu.stuName = "1"; // u2中stu的stuName也变为1 System.out.println(u2.stu.stuName);// 输出1 } }
2. 深层复制
深层复制指即克隆基本类型属性,又克隆引用类型属性。还是上面的例子,如何做到修改u1.stu.stuName的属性,而不影响u2.stu.stuName的属性呢?我们将上面的例子改造下,通过让Student实现克隆接口和重写克隆方法,修改User的克隆方法来处理。
// Student类,实现Cloneable接口 class Student implements Cloneable{ public String stuName; // 重写clone方法 @Override protected Student clone() throws CloneNotSupportedException { return (Student) super.clone(); } } // User类,实现Cloneable接口 class User implements Cloneable{ public int id; public Student stu; public User(int id, Student stu) { this.id = id; this.stu = stu; } // 重写clone方法 @Override protected User clone() throws CloneNotSupportedException { // 克隆一个新对象 User user = (User) super.clone(); // 克隆原对象stu属性 Student stu = this.stu.clone(); // 将克隆的stu属性赋给新对象 user.stu = stu; // 返回新对象 return user; } } //测试类 public class Test { public static void main(String[] args) throws CloneNotSupportedException { Student stu = new Student(); stu.stuName = "测试"; User u1 = new User(1, stu); // 克隆 User u2 = (User) u1.clone(); // 修改u1中stu的属性stuName为1 u1.stu.stuName = "1"; // u2中stu的stuName也变为1 System.out.println(u2.stu.stuName);// 输出不变,还是"测试" } }
时间: 2024-11-06 03:41:30