java對象序列化所引起的循環引用的思考[轉載]
在Java中的模型關系設計中,循環的關系是很常見的,特別是ORM的出現,關系的循環更加有利于維護各自的狀態。但就是這種循環的關系,在java對象序列化時,不可避免的會導致循環引用(Cycle Reference)的問題。
導致CycleReference的情況
還是舉個例子吧(代碼說話):一個很典型,很常見的雙向引用的對象關系。

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

另外一種導致這個問題的情況是,多個對象間關系形成一條回路,跟電學有點像。(具體就不舉例了,在模型設計時,最好還是避免出現這種情況。)
導致這種問題的原因
用jaxb(如果沒有特殊解釋,本文采用的都是jaxb)序列化Company時,無疑會發生循環引用。
當序列化引擎解析Company時,它發現這個對象持有一個Employee的引用,轉而去騷擾Employee。解析Employee時,發現他又持有Company的引用,又轉回Company。如此問題產生。
引擎它并不知道在遇到循環引用問題時,該怎么處理,它只是忠實得按照固定的算法去執行任務。所以我們得讓引擎聰明點,我們得讓引擎遇到這種問題有處理機制。
解決問題
既然需要引擎更聰明,那就沒辦法,就得燒香拜佛,希望制造商的產品擴展性足夠好,考慮了足夠多的情況。
幸運的是,jaxb提供了有這種擴展。(CycleRecoverable接口)
行軍打仗(例子先行):(將以上的例子改下)

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

注意到onCycleDetected方法就是一個回調方法,當遇到循環引用時,jaxb引擎會調用這個方法,用return對象來替換this。所以在這個過程中,就可以將引起循環引用問題的關系斷開,返回給jaxb。
當然Company和Employee對象沒必要全部實現CycleRecoverable接口,但是拿到現實的模型圖中去,誰也保證不了他們不跟別的對象有循環的關系存在。因此還是建議大家把模型都實現這個接口,也好一勞永逸。
希望大家得到了想要的東西。
當一個類實現了序列化接口,有時會遇到 java.io.InvalidClassException 異常出現:
java.io.InvalidClassException: com.test.Test; local class incompatible: stream classdesc serialVersionUID = 7981560250804078637, local class serialVersionUID = -8334405535174160822
這是序列化兼容性所致;
java通過一個名為UID(stream unique identifier)來控制,這個UID是隱式的,它通過類名,方法名等諸多因素經過計算而得,理論上是一一映射的關系,也就是唯一的。如果UID不一樣的話,就無法實現反序列化了,并且將會得到InvalidClassException。
當要人為的產生一個新的版本(實現并沒有改動),而拋棄以前的版本的話,可以通過顯式的聲名UID來實現:
private static final long serialVersionUID=????;//(你可以編造一個UID,但不能有重復)
對于上例我們可以在com.test.Test類中加入 :
private static final long serialVersionUID=7981560250804078637l;
這樣就解決了新老版本的兼容性問題。
當然,對于序列化還有很多問題,慢慢研究吧。
柳德才
13691193654
18942949207
QQ:422157370
liudecai_zan@126.com
湖北-武漢-江夏-廟山
posted on 2009-01-14 13:10 liudecai_zan@126.com 閱讀(1589) 評論(0) 編輯 收藏 所屬分類: 在路上