大話深入淺出Effective Java核心實(shí)戰(zhàn)編程思想之——猴王的把戲
不知道大家還記不記得在《西游記》里的蓮花洞奪寶的故事,就是猴王巧奪寶物,收復(fù)金銀角大王那一章。到底這個(gè)故事給了我們什么啟示呢?這故事又和Effective Java有什么聯(lián)系?還是延續(xù)上篇文章的風(fēng)格吧,看代碼,讀故事。

看到這里你應(yīng)該對深克隆和淺克隆有了初步的了解了吧?現(xiàn)在我們再看怎樣深克隆一個(gè)猴王,哦,不對,應(yīng)該是真正猴王的七十二變。(為什么我叫他猴王,因?yàn)閷O悟空有歧義)。
程序員的一生其實(shí)可短暫了,這電腦一開一關(guān),一天過去了,嚎;電腦一開不關(guān),那就成服務(wù)器了,嚎……

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
// 西天取經(jīng)的路上,金角大王和銀角大王把唐僧抓走了
10
猴王 齊天大圣=new 猴王("齊天大圣孫悟空");
11
//大圣手拿金箍棒,正要收拾金、銀角大王。
12
齊天大圣.取得武器(new 金箍棒());
13
14
/*
15
* 這時(shí)候,金角大王和銀角大王聽聞大圣來者不善,立馬讓小妖去請出他們的寶葫蘆
16
* 當(dāng)然這一切瞞不過神通廣大的大圣爺。大圣猴毛一吹,變出一個(gè)老道士。
17
*/
18
猴王 空悟?qū)O道士=(猴王)齊天大圣.變出一個(gè)化身();
19
空悟?qū)O道士.改名("空悟?qū)O道士");
20
21
/*
22
* 老道士忽悠小妖說他的葫蘆更厲害,能把天都給收了,智力值只有20的小妖看了羨慕不已,要求交換葫蘆。
23
* 老道士自然很樂意,換了葫蘆,直奔妖怪洞穴,收服了金、銀角大王。
24
*/
25
空悟?qū)O道士.取得武器(new 寶葫蘆());
26
27
//問題1:道士拿的是什么武器?道士是由大圣克隆而來,拿的卻不是金箍棒,而是寶葫蘆?
28
assertFalse(齊天大圣.的武器() instanceof 金箍棒);
29
assertTrue(空悟?qū)O道士.的武器() instanceof 寶葫蘆);
30
31
//問題2:大圣和道士拿同一個(gè)武器?
32
assertSame(空悟?qū)O道士.的武器(),齊天大圣.的武器());
33
34
//問題3:既然武器是一樣的,為什么名字又不一樣呢?
35
assertEquals(齊天大圣.名字(),"齊天大圣孫悟空");
36
assertEquals(空悟?qū)O道士.名字(),"空悟?qū)O道士");
37
38
/*
39
* 答案:猴王類繼承了Object.clone(),其克隆原理是:如果類每個(gè)域包含一個(gè)原語類型(primitive)的值,
40
* 或者包含一個(gè)指向非可變(final)對象的引用,那么返回的值或?qū)ο笫且粋€(gè)相同的拷貝;否則,如果是可變類,則會返回相同的引用。
41
* 因?yàn)榻鸸堪纛惒皇欠强勺冾悾鳶tring是,所以你應(yīng)該明白,為什么大圣爺和他的克隆體有不同的名字,卻有相同的武器吧。
42
*
43
* Object.clone()被稱為淺拷貝,或淺克隆。相對應(yīng)的是深克?。╠eep clone),他是指類在克隆時(shí)也拷貝可變對象。
44
* 看到這里你應(yīng)該知道其實(shí)這個(gè)猴王類實(shí)現(xiàn)得不合理,他應(yīng)該擁有一個(gè)深克隆的方法。
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
* 取得一個(gè)猴王的淺克隆化身
58
* @return
59
*/
60
public Object 變出一個(gè)化身(){
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

看到這里你應(yīng)該對深克隆和淺克隆有了初步的了解了吧?現(xiàn)在我們再看怎樣深克隆一個(gè)猴王,哦,不對,應(yīng)該是真正猴王的七十二變。(為什么我叫他猴王,因?yàn)閷O悟空有歧義)。
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
// 西天取經(jīng)的路上,金角大王和銀角大王把唐僧抓走了
14
猴王 齊天大圣=new 猴王("齊天大圣孫悟空");
15
//大圣手拿金箍棒,正要收拾金、銀角大王。
16
齊天大圣.取得武器(new 金箍棒());
17
18
/*
19
* 這時(shí)候,金角大王和銀角大王聽聞大圣來者不善,立馬讓小妖去請出他們的寶葫蘆
20
* 當(dāng)然這一切瞞不過神通廣大的大圣爺。大圣猴毛一吹,變出一個(gè)老道士。
21
*/
22
猴王 空悟?qū)O道士=(猴王)齊天大圣.變出一個(gè)化身();
23
空悟?qū)O道士.改名("空悟?qū)O道士");
24
25
/*
26
* 老道士忽悠小妖說他的葫蘆更厲害,能把天都給收了,智力值只有20的小妖看了羨慕不已,要求交換葫蘆。
27
* 老道士自然很樂意,換了葫蘆,直奔妖怪洞穴,收服了金、銀角大王。
28
*/
29
齊天大圣.取得武器(new 寶葫蘆());
30
31
32
assertTrue(空悟?qū)O道士.的武器() instanceof 金箍棒);
33
assertFalse(空悟?qū)O道士.的武器() instanceof 寶葫蘆);
34
assertNotSame(空悟?qū)O道士.的武器(),齊天大圣.的武器());
35
assertEquals(齊天大圣.名字(),"齊天大圣孫悟空");
36
assertEquals(空悟?qū)O道士.名字(),"空悟?qū)O道士");
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
* 取得一個(gè)猴王的淺克隆化身
49
* @return
50
*/
51
public Object 變出一個(gè)化身(){
52
Object cloneObj=null;
53
try{
54
cloneObj=clone();
55
}catch(CloneNotSupportedException ex){
56
ex.printStackTrace();
57
}
58
return cloneObj;
59
}
60
61
/**
62
* 取得一個(gè)猴王的深克隆化身
63
* @return
64
*/
65
public Object 變出一個(gè)新化身(){
66
Object cloneObj=null;
67
try{
68
cloneObj=clone();
69
}catch(CloneNotSupportedException ex){
70
ex.printStackTrace();
71
}
72
return cloneObj;
73
}
74
75
@Override
76
protected Object clone() throws CloneNotSupportedException{
77
return super.clone();
78
}
79
80
public String 名字() {
81
return name;
82
}
83
84
public void 改名(String name){
85
this.name=name;
86
}
87
88
public 武器 的武器() {
89
return weapon;
90
}
91
92
public void 取得武器(武器 weapon) {
93
this.weapon = weapon;
94
}
95
}
96
97
abstract class 武器 implements Cloneable{
98
public 武器(){
99
100
}
101
102
@Override
103
public Object clone(){
104
Object result=null;
105
try{
106
result= super.clone();
107
}catch(CloneNotSupportedException ex){
108
ex.printStackTrace();
109
}
110
return result;
111
}
112
}
113
114
class 金箍棒 extends 武器{
115
public 金箍棒(){
116
}
117
118
@Override
119
public Object clone(){
120
return super.clone();
121
}
122
}
123
124
class 寶葫蘆 extends 武器{
125
public 寶葫蘆(){
126
}
127
128
@Override
129
public Object clone(){
130
return super.clone();
131
}
132
}
133
}
134

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

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

程序員的一生其實(shí)可短暫了,這電腦一開一關(guān),一天過去了,嚎;電腦一開不關(guān),那就成服務(wù)器了,嚎……
posted on 2009-07-04 14:37 Heis 閱讀(1745) 評論(4) 編輯 收藏 所屬分類: Effective Java