为什么要克隆快速到底
示例代码
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
{@Testpublic void client(){Resume resume = new Resume("Tom", "23", "清华大学", "并发编程");Resume cloneResume = resume.clone();System.out.println(resume == cloneResume); // falseSystem.out.println(resume.getClass() == cloneResume.getClass()); // trueSystem.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()方法三条规则
浅克隆和深克隆