java(12)克隆的两种方式

Posted on 2023-01-31 09:37  弯弓射雕的男人  阅读(49)  评论(0编辑  收藏  举报

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     }