Oo緣來是你oO


          posts - 120,comments - 125,trackbacks - 0
          ????????????????????????????? 在Java中使用循環(huán)定義會(huì)出現(xiàn)哪些問題 ?

          ??????????????????????????????????????????????
          馬嘉楠 ??????? 2006-10-19


          在上一篇文章《 inconstant constants ( 變化無常的常量 ) ? 》的基礎(chǔ)上,我們?cè)賮硌芯恳幌?font color="#000000">在 Java 中使用循環(huán)定義會(huì)出現(xiàn)哪些問題。

          老規(guī)矩,代碼伺候 ^+^

          例1:

          public class
          ClassX{
          ???public?static?final?intX?=?2*
          ClassY.Y;
          }

          public?class
          ClassY{
          ???public?static?final?intY?=ClassZ.Z+?1
          ;
          }

          public class ?ClassZ? extends
          ClassX{
          ???public?static?final?int?Z=?X?+?3
          ;
          }

          public class?
          ClassTest{
          ???public?static?void
          main(String[]?args){
          ??????System.out.println(ClassX.X
          + ClassY.Y +
          ClassZ.Z);
          ???}
          }


          代碼中的static final變量X,Y,Z,循環(huán)定義。

          你可以先想一下,這個(gè)值會(huì)是多少?看看與實(shí)際結(jié)果是否一致。

          輸出結(jié)果:


          現(xiàn)在對(duì)ClassTest.java進(jìn)行一點(diǎn)修改,如下:

          例2:

          public?class
          ClassTest{
          ???public?staticvoid
          main(String[]?args){
          ??????System.out.println(ClassZ.Z
          + ClassY.Y +
          ClassX.X);
          ???}
          }

          兩次的輸出結(jié)果會(huì)一樣么?
          我既然這么問了,你肯定會(huì)說不一樣,那你知道原因么?你知道這次的輸出結(jié)果么?
          可以先思考一下。

          輸出結(jié)果:


          讓我來告訴你這是怎么回事。

          我們可以看見,對(duì)于三個(gè)staitc final 變量 X,Y,Z,他們的初始化表達(dá)式是循環(huán)定義的。在編譯期間不能確定它們的值,所以它們是運(yùn)行期間常量( runtime constants ),編譯器不會(huì)進(jìn)行常量替換。
          而且每個(gè)表達(dá)式的計(jì)算將會(huì)依賴于類裝載的順序。

          例如,為了計(jì)算出例1中的 ClassTest 結(jié)果,我們可以預(yù)見,ClassX 是第一個(gè)被裝載的類,但是第一個(gè)完成初始化的類卻是 ClassZ.

          讓我們一步一步看看都發(fā)生了什么。

          1.???X = 2 * ClassY.Y;??????計(jì)算X,需要知道ClassY.Y的值,下一步計(jì)算Y值
          2.???Y = ClassZ.Z + 1;??????計(jì)算Y,需要知道ClassZ.Z的值,下一步計(jì)算Z值
          3.???Z = X + 3;??????????????? 計(jì)算Z,需要知道X的值,而此時(shí)X的值還沒有被計(jì)算出來(又轉(zhuǎn)回來了,居然是個(gè)圈,呵呵^+^),所以我們使用X的默認(rèn)值0。

          因此:
          ??????Z = 3;
          ??????Y = 4;
          ??????X = 8;

          所以 ClassX.X + ClassY.Y + ClassZ.Z? =? 15

          例2當(dāng)中,也是同一道理
          不同的是,ClassZ是第一個(gè)被裝載的類,ClassX是第一個(gè)完成初始化的類
          1. Z = X + 3;
          2. X = 2 * ClassY.Y;
          3. Y = ClassZ.Z + 1;(此時(shí)使用Z的默認(rèn)值0)

          因此:
          ??????Y = 1;
          ??????X = 2;
          ??????Z = 5;

          所以 ClassZ.Z + ClassY.Y + ClassX.X = 8

          只是簡(jiǎn)單的改變的輸出順序,結(jié)果卻截然不同。哪一個(gè)才是你想要得結(jié)果呢?

          我的例子看起來有點(diǎn)挖空心思鉆牛角尖,但是在大型項(xiàng)目當(dāng)中,也許就會(huì)出現(xiàn)與例子當(dāng)中相同的循環(huán)定義,如果真的存在的話,那么在紛繁的代碼當(dāng)中想要發(fā)現(xiàn)循環(huán)定義可不是件容易的事情。

          如果獨(dú)立看每一個(gè)定義的話,似乎都可以進(jìn)行常量替換,看不出任何問題。但是這樣的代碼在不久的將來就會(huì)引發(fā)問題,而且不易被我們所察覺。

          在你的應(yīng)用程序當(dāng)中不經(jīng)意的代碼改變(例如示例代碼中我們只是改變了輸出順序,卻產(chǎn)生了截然不同的結(jié)果),就會(huì)導(dǎo)致不同的類裝載順序和計(jì)算順序,或者在并發(fā)的線程調(diào)度中,可能也會(huì)導(dǎo)致致不同的類裝載順序和計(jì)算順序。不幸的是,大多數(shù)編譯器不認(rèn)為這種代碼是錯(cuò)誤,也不會(huì)對(duì)編程人員給出任何警告。

          我只是講了一下循環(huán)定義會(huì)引發(fā)的問題,我暫時(shí)也想不出什么好的解決辦法,只能在編程的過程當(dāng)中盡量注意啦。


          注:有錯(cuò)誤請(qǐng)告訴我,非常感謝!



          馬嘉楠
          jianan.ma@gmail.com

          posted on 2006-10-19 10:58 馬嘉楠 閱讀(2028) 評(píng)論(4)  編輯  收藏 所屬分類: Java

          FeedBack:
          # re: 在java中使用循環(huán)定義會(huì)出現(xiàn)哪些問題?
          2006-10-19 12:56 | 尚元秋
          是不是很好玩啊  回復(fù)  更多評(píng)論
            
          # re: 在java中使用循環(huán)定義會(huì)出現(xiàn)哪些問題?
          2006-10-19 17:44 | rainsf
          很無聊的問題  回復(fù)  更多評(píng)論
            
          # re: 在java中使用循環(huán)定義會(huì)出現(xiàn)哪些問題?
          2006-10-19 21:13 | Web 2.0 技術(shù)資源
          誰這樣寫代碼~ 就槍斃他!  回復(fù)  更多評(píng)論
            
          # re: 在java中使用循環(huán)定義會(huì)出現(xiàn)哪些問題?
          2007-01-09 10:53 | 菜包
          又學(xué)到鳥  回復(fù)  更多評(píng)論
            
          主站蜘蛛池模板: 扬中市| 成都市| 许昌市| 东辽县| 子长县| 宁化县| 宁国市| 济源市| 鸡泽县| 中卫市| 洛阳市| 兴隆县| 临桂县| 芜湖市| 辛集市| 汉寿县| 台东县| 鄢陵县| 刚察县| 安平县| 廉江市| 永宁县| 全椒县| 凤凰县| 田阳县| 华亭县| 西和县| 高雄市| 汽车| 张北县| 高淳县| 长乐市| 仙游县| 无棣县| 玉环县| 松阳县| 西藏| 林周县| 自治县| 孟津县| 彭阳县|