不知道大家还记不记得在《西游记》里的莲花洞夺宝的故事,就是猴王巧夺宝物,收复金银角大王那一章。到底这个故事给了我们什么启示呢?这故事又和Effective Java有什么联系?还是延续上篇文章的风格吧,看代码,读故事。
1
import
static
org.junit.Assert.
*
;
2
import
org.junit.Test;
3
4
5
public
class
TestClone
{
6
7
@Test
8
public
void
testClone()
{
9
//
西天取经的路上,金角大王和银角大王把唐僧抓走了
10
猴王 齐天大圣
=
new
猴王(
"
齐天大圣孙悟空
"
);
11
//
大圣手拿金箍棒,正要收拾金、银角大王。
12
齐天大圣.取得武器(
new
金箍棒());
13
14
/**/
/*
15
* 这时候,金角大王和银角大王听闻大圣来者不善,立马让小妖去请出他们的宝葫芦
16
* 当然这一切瞒不过神通广大的大圣爷。大圣猴毛一吹,变出一个老道士。
17
*/
18
猴王 空悟孙道士
=
(猴王)齐天大圣.变出一个化身();
19
空悟孙道士.改名(
"
空悟孙道士
"
);
20
21
/**/
/*
22
* 老道士忽悠小妖说他的葫芦更厉害,能把天都给收了,智力值只有20的小妖看了羡慕不已,要求交换葫芦。
23
* 老道士自然很乐意,换了葫芦,直奔妖怪洞穴,收服了金、银角大王。
24
*/
25
空悟孙道士.取得武器(
new
宝葫芦());
26
27
//
问题1:道士拿的是什么武器?道士是由大圣克隆而来,拿的却不是金箍棒,而是宝葫芦?
28
assertFalse(齐天大圣.的武器()
instanceof
金箍棒);
29
assertTrue(空悟孙道士.的武器()
instanceof
宝葫芦);
30
31
//
问题2:大圣和道士拿同一个武器?
32
assertSame(空悟孙道士.的武器(),齐天大圣.的武器());
33
34
//
问题3:既然武器是一样的,为什么名字又不一样呢?
35
assertEquals(齐天大圣.名字(),
"
齐天大圣孙悟空
"
);
36
assertEquals(空悟孙道士.名字(),
"
空悟孙道士
"
);
37
38
/**/
/*
39
* 答案:猴王类继承了Object.clone(),其克隆原理是:如果类每个域包含一个原语类型(primitive)的值,
40
* 或者包含一个指向非可变(final)对象的引用,那么返回的值或对象是一个相同的拷贝;否则,如果是可变类,则会返回相同的引用。
41
* 因为金箍棒类不是非可变类,而String是,所以你应该明白,为什么大圣爷和他的克隆体有不同的名字,却有相同的武器吧。
42
*
43
* Object.clone()被称为浅拷贝,或浅克隆。相对应的是深克隆(deep clone),他是指类在克隆时也拷贝可变对象。
44
* 看到这里你应该知道其实这个猴王类实现得不合理,他应该拥有一个深克隆的方法。
45
*/
46
}
47
48
class
猴王
implements
Cloneable
{
49
private
String name;
50
private
武器[] weapon
=
new
武器[
1
];
51
52
public
猴王(String name)
{
53
this
.name
=
name;
54
}
55
56
/** */
/**
57
* 取得一个猴王的浅克隆化身
58
*
@return
59
*/
60
public
Object 变出一个化身()
{
61
Object cloneObj
=
null
;
62
try
{
63
cloneObj
=
clone();
64
}
catch
(CloneNotSupportedException ex)
{
65
ex.printStackTrace();
66
}
67
return
cloneObj;
68
}
69
70
@Override
71
protected
Object clone()
throws
CloneNotSupportedException
{
72
return
super
.clone();
73
}
74
75
public
String 名字()
{
76
return
name;
77
}
78
79
public
void
改名(String name)
{
80
this
.name
=
name;
81
}
82
83
public
武器 的武器()
{
84
return
weapon[
0
];
85
}
86
87
public
void
取得武器(武器 weapon)
{
88
this
.weapon[
0
]
=
weapon;
89
}
90
}
91
92
class
武器
{
93
public
武器()
{
94
95
}
96
}
97
98
class
金箍棒
extends
武器
{
99
public
金箍棒()
{
100
}
101
}
102
103
class
宝葫芦
extends
武器
{
104
public
宝葫芦()
{
105
}
106
}
107
108
109
}
110

2

3

4

5



6

7

8



9

10

11

12

13

14


15

16

17

18

19

20

21


22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38


39

40

41

42

43

44

45

46

47

48



49

50

51

52



53

54

55

56


57

58

59

60



61

62



63

64



65

66

67

68

69

70

71



72

73

74

75



76

77

78

79



80

81

82

83



84

85

86

87



88

89

90

91

92



93



94

95

96

97

98



99



100

101

102

103



104



105

106

107

108

109

110

看到这里你应该对深克隆和浅克隆有了初步的了解了吧?现在我们再看怎样深克隆一个猴王,哦,不对,应该是真正猴王的七十二变。(为什么我叫他猴王,因为孙悟空有歧义)。
1
import
static
org.junit.Assert.assertEquals;
2
import
static
org.junit.Assert.assertFalse;
3
import
static
org.junit.Assert.assertNotSame;
4
import
static
org.junit.Assert.assertTrue;
5
6
import
org.junit.Test;
7
8
9
public
class
TestDeepClone
{
10
11
@Test
12
public
void
testDeepClone()
{
13
//
西天取经的路上,金角大王和银角大王把唐僧抓走了
14
猴王 齐天大圣
=
new
猴王(
"
齐天大圣孙悟空
"
);
15
//
大圣手拿金箍棒,正要收拾金、银角大王。
16
齐天大圣.取得武器(
new
金箍棒());
17
18
/**/
/*
19
* 这时候,金角大王和银角大王听闻大圣来者不善,立马让小妖去请出他们的宝葫芦
20
* 当然这一切瞒不过神通广大的大圣爷。大圣猴毛一吹,变出一个老道士。
21
*/
22
猴王 空悟孙道士
=
(猴王)齐天大圣.变出一个化身();
23
空悟孙道士.改名(
"
空悟孙道士
"
);
24
25
/**/
/*
26
* 老道士忽悠小妖说他的葫芦更厉害,能把天都给收了,智力值只有20的小妖看了羡慕不已,要求交换葫芦。
27
* 老道士自然很乐意,换了葫芦,直奔妖怪洞穴,收服了金、银角大王。
28
*/
29
齐天大圣.取得武器(
new
宝葫芦());
30
31
32
assertTrue(空悟孙道士.的武器()
instanceof
金箍棒);
33
assertFalse(空悟孙道士.的武器()
instanceof
宝葫芦);
34
assertNotSame(空悟孙道士.的武器(),齐天大圣.的武器());
35
assertEquals(齐天大圣.名字(),
"
齐天大圣孙悟空
"
);
36
assertEquals(空悟孙道士.名字(),
"
空悟孙道士
"
);
37
}
38
39
class
猴王
implements
Cloneable
{
40
private
String name;
41
private
武器 weapon;
42
43
public
猴王(String name)
{
44
this
.name
=
name;
45
}
46
47
/** */
/**
48
* 取得一个猴王的浅克隆化身
49
*
@return
50
*/
51

2

3

4

5

6

7

8

9



10

11

12



13

14

15

16

17

18


19

20

21

22

23

24

25


26

27

28

29

30

31

32

33

34

35

36

37

38

39



40

41

42

43



44

45

46

47


48

49

50

51