1.Java克隆的两种方式
浅拷贝
深拷贝
在Java中,我们说两个对象是否相等通常有两层含义:
对象的内容是否相等,通常使用到对象的 equals(Object o) 函数;
引用的地址是否相同,使用运算符 == 比较即可。
当两个对象通过赋值符号 = 赋值时,表明这两个对象指向了内存中同一个地址,所以改变其中一个对象的内容,也就间接地改变了另一个对象的内容。有时候,我们需要从一个已经存在的对象重新拷贝一份出来,并且不仅这两个对象内容相等,在内存中存在两个独立的存储地址,互不影响,这时,就需要用到 Java 中的克隆机制。
2.Cloneable
通过 Cloneable 接口可以很轻松地实现 Java 对象的克隆,只需要 implements Cloneable 并实现 Object 的 clone() 方法即可。
1 public class User implements Cloneable{ 2 3 private String username; 4 5 private String password; 6 7 public User(String username, String password) { 8 super(); 9 this.username = username; 10 this.password = password; 11 } 12 13 public String getUsername() { 14 return username; 15 } 16 17 public void setUsername(String username) { 18 this.username = username; 19 } 20 21 public String getPassword() { 22 return password; 23 } 24 25 public void setPassword(String password) { 26 this.password = password; 27 } 28 29 @Override 30 protected Object clone() throws CloneNotSupportedException { 31 return super.clone(); 32 } 33 34 @Override 35 public boolean equals(Object obj) { 36 User user = (User) obj; 37 if (username.equals(user.username) && password.equals(user.password)) { 38 return true; 39 } 40 return false; 41 } 42 43 }
注意这里对象实现的是 Object 类的 clone() 方法,因为 Cloneable 是一个空接口
1 package java.lang; 2 3 public interface Cloneable { 4 }
从 clone() 函数的注释中能够看出对象与克隆对象之间的关系,测试代码如下(注意:我们在 User 对象中重写了 equals() 函数)
1 public static void main(String[] args) throws CloneNotSupportedException{ 2 User userOne, userTwo, userThree; 3 userOne = new User("username", "password"); 4 userTwo = userOne; 5 userThree = (User) userOne.clone(); 6 7 System.out.println(userTwo==userOne); //true 8 System.out.println(userTwo.equals(userOne)); //true 9 10 System.out.println(userThree==userOne); //false 11 System.out.println(userThree.equals(userOne)); //true 12 13 }测试结果显示,通过 clone() 函数,我们成功地从 userOne 对象中克隆出了一份独立的 userThree 对象。
3.浅拷贝与深拷贝的区别
3.1浅拷贝
1 public class Company implements Cloneable{ 2 3 private User user; 4 5 private String address; 6 7 public Company(User user, String address) { 8 super(); 9 this.user = user; 10 this.address = address; 11 } 12 13 public User getUser() { 14 return user; 15 } 16 17 public void setUser(User user) { 18 this.user = user; 19 } 20 21 public String getAddress() { 22 return address; 23 } 24 25 public void setAddress(String address) { 26 this.address = address; 27 } 28 29 @Override 30 protected Object clone() throws CloneNotSupportedException { 31 return super.clone(); 32 } 33 34 @Override 35 public boolean equals(Object obj) { 36 Company company = (Company) obj; 37 if (user.equals(company.getUser()) && address.equals(company.address)) { 38 return true; 39 } 40 return false; 41 } 42 43 }测试结果如下:
1 public static void main(String[] args) throws CloneNotSupportedException{ 2 Company companyOne, companyTwo, companyThree; 3 companyOne = new Company(new User("username", "password"), "上海市"); 4 companyTwo = companyOne; 5 companyThree = (Company) companyOne.clone(); 6 7 System.out.println(companyTwo==companyOne); //true 8 System.out.println(companyTwo.equals(companyOne)); //true 9 10 System.out.println(companyThree==companyOne); //false 11 System.out.println(companyThree.equals(companyOne)); //true 12 13 System.out.println(companyThree.getUser()==companyOne.getUser()); //true ? 这里为什么不是false呢 14 System.out.println(companyThree.getUser().equals(companyOne.getUser())); //true 15 16 }