由原型模式引出的关于Cloneable接口和Object的clone()方法的一些问题

为什么要克隆快速到底

示例代码

 1 class Resume
 2 {
 3     private String name;
 4     private String age;
 5     private String university;
 6     private String specialSkills;
 7     
 8     public Resume(String name, String age, String university, String specialSkills)
 9     {
10         this.name = name;
11         this.age = age;
12         this.university = university;
13         this.specialSkills = specialSkills;
14     }
15 
16     public String selfProduce()
17     {
18         return "我叫"+ name+",今年"+age+",毕业于"+university+",擅长于"+specialSkills+".";
19     }
20 }

客户端

 1 public class Client
 2 {
 3     @Test
 4     public void client()
 5     {
 6         Resume resume = new Resume("Tom","23","清华大学","并发编程");
 7         System.out.println(resume.selfProduce());
 8         
 9     }
10 }

如果我现在想把这份简历复印一份在这个基础上修改一下,根据不同的公司对于岗位的技能要求,只需要修改一下 specialSkills,显然我不能重新 new Resume(),因为里面的数据还要重新填,也不能直接在这份上面改,因为这份也要用,我就想复印一份跟它一样的。

示例代码

 1 class Resume implements Cloneable // 如果不实现这个接口就会报 cloneNotSupportExceptoin
 2 {
 3     private String name;
 4     private String age;
 5     private String university;
 6     private String specialSkills;
 7 
 8     public Resume()
 9     {
10         System.out.println("Resume 被初始化了");
11     }
12     
13     public Resume(String name, String age, String university, String specialSkills)
14     {
15         this.name = name;
16         this.age = age;
17         this.university = university;
18         this.specialSkills = specialSkills;
19         System.out.println("Resume 被初始化了hahaha");
20     }
21 
22     public String getSpecialSkills()
23     {
24         return specialSkills;
25     }
26 
27     public void setSpecialSkills(String specailSkills)
28     {
29         this.specialSkills = specailSkills;
30     }
31 
32     public String selfProduce()
33     {
34         return "我叫" + name + ",今年" + age + ",毕业于" + university + ",擅长于" + specialSkills + ".";
35     }
36 
37     public Resume clone()
38     {
39         Resume clone = null;
40         try
41         {
42             clone = (Resume) super.clone();
43         } catch (CloneNotSupportedException e)
44         {
45             e.printStackTrace();
46         }
47         return clone;
48     }
49 }

 客户端

 1 public class Client
 2 {
 3     @Test
 4     public void client()
 5     {
 6         Resume resume = new Resume("Tom", "23", "清华大学", "并发编程");
 7         System.out.println("这是原简历-----" + resume.selfProduce());
 8         Resume cloneResume = resume.clone();
 9         cloneResume.setSpecialSkills("分布式架构");
10         System.out.println("这是复印件-----" + cloneResume.selfProduce());
11     }
12 }

 运行结果

Resume 被初始化了hahaha
这是原简历-----我叫Tom,今年23,毕业于清华大学,擅长于并发编程. 这是复印件-----我叫Tom,今年23,毕业于清华大学,擅长于分布式架构.

 这就达到了我们的目的了。克隆本质上是:在堆中克隆出一块和原对象一样的对象,并将这个对象的地址赋予新的引用。

 Cloneable接口和Object的clone()方法

  Java中实现了Cloneable接口的类有很多,像我们熟悉的 ArrayList、Calendar、Date、HashMap、Hashtable、HashSet、LinkedList 等等。还是那句话,对于不熟悉的接口、方法,第一反应一定是查询 JDK API 。

1、Cloneable 接口

(1)一个类如果实现了 Cloneable 接口,就表示 Object 的 clone() 方法可以合法地对该类实例进行按字段复制

(2)如果在没有实现 Cloneable 接口的实例上调用 Object 的 clone() 方法,则会导致抛出 CloneNotSupporteddException

(3)按照惯例,实现此接口的类应该使用公共方法重写 Object 的 clone() 方法,Object 的 clone() 方法是一个受保护的方法

2、Object 的 clone() 方法

创建并返回此对象的一个副本。对于任何对象 x,表达式:

(1)x.clone() != x 为 true

(2)x.clone().getClass() == x.getClass() 为 true

(3)x.clone().equals(x) 一般情况下为 true,但这并不是必须要满足的要求

public class Client
{
    @Test
    public void client()
    {
        Resume resume = new Resume("Tom", "23", "清华大学", "并发编程");
        Resume cloneResume = resume.clone();
        
        System.out.println(resume == cloneResume); // false
        System.out.println(resume.getClass() == cloneResume.getClass()); // true
        System.out.println(resume.equals(cloneResume)); // false
    }
}

运行结果

Resume 被初始化了hahaha
false
true
false

 第三个为 false 的原因是,这个对象的 equals 方法并没有重写,而是调用的是 Object 类的 equals 方法

public boolean equals(Object obj) 
{
return (this == obj); }

得到两个个结论:

1、克隆一个对象并不会调用对象的构造方法,因为 "Resume 被初始化了hahaha" 语句只出现了一次

2、符合JDK API的clone()方法三条规则

 

浅克隆和深克隆

 

 

转载于:https://www.cnblogs.com/tkzL/p/8782334.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值