<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Oo緣來(lái)是你oO


    posts - 120,comments - 125,trackbacks - 0

    ????????????????????? ????????? inconstant constants ( 變化無(wú)常的常量 )??
    ??????????????????????????????????????????
    ??????????????????????????????????????????
    馬嘉楠 ?????????????? 2006-10-18


    看到這個(gè)題目也許你會(huì)感到奇怪,會(huì)想我在胡說(shuō)八道什么,一定又是起個(gè)怪異的名字,騙取點(diǎn)擊率。還請(qǐng)你耐心看完,如果你有所收獲,那么我很高興;如果你還是覺(jué)得上當(dāng)了,那我繼續(xù)努力寫出點(diǎn)有用的東西,呵呵。

    其實(shí)我想了很久,也還是不知道起一個(gè)什么題目好,就套用了《 The Java Language Specification 》中的一個(gè)名詞“ inconstant constants”,我把他翻譯成“變化無(wú)常的常量

    注:部分內(nèi)容在《 使用Java中的final變量需要注意的地方 》有提到,不過(guò)我轉(zhuǎn)載的原文不夠詳細(xì)深入,這才重新寫一下。

    我們還是來(lái)先看一段代碼,由代碼引出問(wèn)題:

    public class ?ClassX?{
    ???
    public static final int ??X?? = ??? 2
    ?;
    }

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


    輸出結(jié)果:

    2

    結(jié)果是顯而易見(jiàn)的,這里需要說(shuō)明的是:
    根據(jù)Java語(yǔ)言規(guī)范,對(duì)于java中的static final變量,如果用一個(gè)在編譯期間(complie time)可以計(jì)算出結(jié)果的表達(dá)式進(jìn)行初始化,則用到此變量的地方會(huì)被該表達(dá)式的結(jié)果所替代。本例中,在編譯期間,ClassTest.main() 函數(shù)中 ClassX.X 將被2所替代。

    此時(shí),在類ClassTest main()中不再有指向ClassX的動(dòng)態(tài)鏈接,告訴ClassTest在運(yùn)行的時(shí)候從ClassX獲得X的值,你可以通過(guò)使用javap反編譯器幫助你理解。

    1. 先編譯ClassTest.java文件
    ????????????javac ClassTest.java
    2. 使用javap
    ????????????javap -c ClassTest

    屏幕輸出:

    Complied?from?"ClassTest.java"
    public?class?ClassTest?extends?java.lang.Object{
    public?ClassTest();
    ???Code:
    ??????0:?aload_0
    ??????1:?invokespecial?????#1;?//Method?java/lang/Object."<init>
    ":()V
    ??????4:?return

    public?static?void?main(java.lang.String[]);
    ???Code:
    ??????0:?getstatic?????????#2;?//Field?java/lang/System.out:Ljava/io/PrintStream;
    ??????3:?iconst_2?
    ??????4:?invokevirtua??????#3;?//Method?java/io/PrintStream.println:(I)V
    ??????7:?return

    }


    可以看出,在調(diào)用System.out.println()之前,整數(shù)2已經(jīng)被放在JVM的堆棧中,不再有指向ClassX.X的鏈接。如果此時(shí),改變ClassX.X的值為1,并且重新編譯ClassX.X文件,但是并不重新編譯ClassTest.java文件,運(yùn)行ClassTest,輸出結(jié)果仍然是2.

    這么做(常量替換)的一個(gè)原因是為了在編譯期間檢查switch case語(yǔ)句。switch語(yǔ)句中的每一個(gè)case都需要一個(gè)常量值,而且每?jī)蓚€(gè)之間都不能相同,編譯器在編譯期間將會(huì)做檢查。

    如果用來(lái)給static final變量進(jìn)行初始化的表達(dá)式,只能在運(yùn)行時(shí)刻才可以計(jì)算出值,那么常量替換就不會(huì)發(fā)生.例如:

    public class ClassX?{
    ???public static?final?int?X?=?new?
    java.util.Random().nextInt();
    } ?


    ClassX 改變了,我們?cè)賮?lái)看一下Main.main():

    Complied?from?"ClassTest.java"
    public?class?ClassTest?extends?java.lang.Object{
    public?ClassTest();
    ???Code:
    ??????0:?aload_0
    ??????1:?invokespecial??????#1;?//Method?java/lang/Object."<init>
    ":()V
    ??????4:?return

    public?static?void?main(java.lang.String[]);
    ???Code:
    ??????0:?getstatic????????? #2;?//Field?java/lang/System.out:Ljava/io/PrintStream;
    ??????3:?getstatic????????? #3;?//Field?ClassX.X:I?
    ??????6:?invokevirtual??????#4;?//Method?java/io/PrintStream.println:(I)V
    ??????9:?return

    }


    此時(shí)我們可以看見(jiàn)有個(gè)引用指向了Field X。
    ( 如果把類ClassX改成Interface,仍然會(huì)出現(xiàn)上面的結(jié)果 )

    當(dāng)然有方法可以使你避免出現(xiàn)"inconstant constants"問(wèn)題。

    第一種方法:
    當(dāng)你要聲明一個(gè)編譯期間常量的時(shí)候,一定要保證此變量不會(huì)或者不太可能改變,或者盡量少使用聲明為static final的變量。當(dāng)然這只能治標(biāo)不能治本,所以我推薦使用第二種方法。

    第二種方法:
    將變量聲明為private,同時(shí)聲明一個(gè)方法來(lái)獲得此變量的值

    // ClassX.java修改如下:?
    public class? ClassX?{
    ???private?static?final?int?X?=?2
    ;
    ???public? static int
    getX(){
    ??????return
    X;
    ???}
    }

    // ClassTest.java修改如下:?

    public?class? ClassTest{
    ???public?static?void?
    main(String[]?args){
    ??????System.out.println(ClassX.getX());
    ???}
    }


    此時(shí)再改變ClassX.X的值為1,重新編譯ClassX.java,而不編譯ClassTest,結(jié)果就會(huì)顯示1,而非2。這就避免了"inconstant constants"的問(wèn)題。

    下一篇準(zhǔn)備講一下
    《在java中使用循環(huán)定義會(huì)出現(xiàn)哪些問(wèn)題?》


    ?



    馬嘉楠
    jianan.ma@gmail.com

    posted on 2006-10-18 16:27 馬嘉楠 閱讀(1623) 評(píng)論(5)  編輯  收藏 所屬分類: Java

    FeedBack:
    # re: inconstant constants(變化無(wú)常的常量)
    2006-10-18 21:24 | Flyingis
    下次記得可以將字體大小和格式稍調(diào)整一下,看起來(lái)舒服一點(diǎn)。

    寫的不錯(cuò)啊。  回復(fù)  更多評(píng)論
      
    # re: inconstant constants(變化無(wú)常的常量)
    2006-10-18 22:08 | 馬嘉楠
    @Flyingis
    謝謝^+^

    我把字體改為3號(hào)了,確實(shí)看起來(lái)舒服很多
    問(wèn)一下你得代碼和文字都用什么字體啊?
    我總是調(diào)不好  回復(fù)  更多評(píng)論
      
    # re: inconstant constants(變化無(wú)常的常量)
    2006-10-19 10:26 | Flyingis
    1.Word/OneNote直接粘貼過(guò)來(lái)的文章多余代碼比較多,格式會(huì)有問(wèn)題,建議在粘貼過(guò)來(lái)后清除一下Word代碼。
    2.正文字號(hào)我一般用2號(hào)。
    3.漢字字體為宋體,英文字母為Verdana,全選然后選擇字體為Verdana即可,漢字默認(rèn)就是宋體。  回復(fù)  更多評(píng)論
      
    # re: inconstant constants(變化無(wú)常的常量)
    2006-10-19 10:40 | 馬嘉楠
    我都是先在記事本上面寫的,寫得差不多了,粘貼過(guò)來(lái),再做些修改就發(fā)布。

    今天凌晨開(kāi)始就有問(wèn)題了,開(kāi)始不能登陸,之后就一直不能編輯,也許新版本升級(jí)?維護(hù)不用這么長(zhǎng)時(shí)間吧。

    等可以編輯了,再來(lái)修改一下  回復(fù)  更多評(píng)論
      
    # re: inconstant constants(變化無(wú)常的常量)
    2006-10-19 11:21 | 馬嘉楠
    60天內(nèi)閱讀排行
    增加了這個(gè)功能
    還是不能編輯,不知道還有什么東西改動(dòng)

    應(yīng)該貼一個(gè)公告出來(lái)啊  回復(fù)  更多評(píng)論
      
    主站蜘蛛池模板: 亚洲好看的理论片电影| 无码人妻一区二区三区免费n鬼沢| 国产亚洲高清不卡在线观看| 女人被免费视频网站| 无码人妻丰满熟妇区免费| 成人午夜影视全部免费看| 色噜噜亚洲男人的天堂| 久久精品国产亚洲AV麻豆王友容| 国产精品国产自线拍免费软件| 91精品国产免费| 成人av片无码免费天天看| 国产亚洲综合久久| 亚洲精品人成网在线播放影院| 久久青青草原亚洲AV无码麻豆| 日韩精品亚洲专区在线观看| 我要看免费的毛片| 可以免费看的卡一卡二| 免费无码VA一区二区三区| a毛看片免费观看视频| 新最免费影视大全在线播放| 亚洲精品国产高清在线观看| 亚洲AV一二三区成人影片| 亚洲AV无码国产精品色午友在线 | 亚洲精品人成无码中文毛片| 成人啪精品视频免费网站| 18禁免费无码无遮挡不卡网站| 污污网站18禁在线永久免费观看| 91在线视频免费观看| 亚洲阿v天堂在线2017免费| 一级做a爰黑人又硬又粗免费看51社区国产精品视 | 1a级毛片免费观看| 99精品视频在线观看免费专区| 久久久WWW成人免费精品| 国产99视频精品免费视频76| 一级特级aaaa毛片免费观看| 免费国产黄网站在线看| 最新亚洲人成无码网站| 国产产在线精品亚洲AAVV| 国产成人综合亚洲绿色| 特级aa**毛片免费观看| 国产亚洲精品国产福利在线观看|