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

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

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

    我的漫漫程序之旅

    專注于JavaWeb開發(fā)
    隨筆 - 39, 文章 - 310, 評論 - 411, 引用 - 0
    數(shù)據(jù)加載中……

    盡情享受每一個Byte

    下面的程序循環(huán)遍歷byte數(shù)值,以查找某個特定值。這個程序會打印出什么呢?
    public class BigDelight {
        
    public static void main(String[] args) 
    {
            
    for (byte b = Byte.MIN_VALUE; b < Byte.MAX_VALUE; b++
    {
                 
    if (b == 0x90
    )
                     System.out.print(
    "Joy!"
    );
            }

        }

    }

    這個循環(huán)在除了Byte.MAX_VALUE之外所有的byte數(shù)值中進行迭代,以查找0x90。這個數(shù)值適合用byte表示,并且不等于Byte.MAX_VALUE,因此你可能會想這個循環(huán)在該迭代會找到它一次,并將打印出Joy!。但是,所見為虛。如果你運行該程序,就會發(fā)現(xiàn)它沒有打印任何東西。怎么回事?

    簡單地說,0x90是一個int常量,它超出了byte數(shù)值的范圍。這與直覺是相悖的,因為0x90是一個兩位的十六進制字面常量,每一個十六進制位都占據(jù)4個比特的位置,所以整個數(shù)值也只占據(jù)8個比特,即1個byte。問題在于byte是有符號類型。常量0x90是一個正的最高位被置位的8位int數(shù)值。合法的byte數(shù)值是從-128到+127,但是int常量0x90等于+144。

    拿一個byte與一個int進行的比較是一個混合類型比較(mixed-type comparison)。如果你把byte數(shù)值想象為蘋果,把int數(shù)值想象成為桔子,那么該程序就是在拿蘋果與桔子比較。請考慮表達式((byte)0x90 == 0x90),盡管外表看起來是成立的,但是它卻等于false。

    為了比較byte數(shù)值(byte)0x90和int數(shù)值0x90,Java通過拓寬原始類型轉(zhuǎn)換將byte提升為一個int[JLS 5.1.2],然后比較這兩個int數(shù)值。因為byte是一個有符號類型,所以這個轉(zhuǎn)換執(zhí)行的是符號擴展,將負的byte數(shù)值提升為了在數(shù)字上相等的int數(shù)值。在本例中,該轉(zhuǎn)換將(byte)0x90提升為int數(shù)值-112,它不等于int數(shù)值0x90,即+144。

    由于系統(tǒng)總是強制地將一個操作數(shù)提升到與另一個操作數(shù)相匹配的類型,所以混合類型比較總是容易把人搞糊涂。這種轉(zhuǎn)換是不可視的,而且可能不會產(chǎn)生你所期望的結(jié)果。有若干種方法可以避免混合類型比較。我們繼續(xù)有關(guān)水果的比喻,你可以選擇拿蘋果與蘋果比較,或者是拿桔子與桔子比較。你可以將int轉(zhuǎn)型為byte,之后你就可以拿一個byte與另一個byte進行比較了:

    if (b == (byte)0x90)
        System.out.println(
    "Joy!"
    );
    或者,你可以用一個屏蔽碼來消除符號擴展的影響,從而將byte轉(zhuǎn)型為int,之后你就可以拿一個int與另一個int進行比較了:
    if ((b & 0xff== 0x90)
        System.out.print(
    "Joy!"
    );
    上面的兩個解決方案都可以正常運行,但是避免這類問題的最佳方法還是將常量值移出到循環(huán)的外面,并將其在一個常量聲明中定義它。下面是我們對此作出的第一個嘗試:
    public class BigDelight {
        
    private static final byte TARGET = 0x90
    ;   
        
    public static void main(String[] args) 
    {
            
    for (byte b = Byte.MIN_VALUE; b <
     
                 Byte.MAX_VALUE; b
    ++
    {
                 
    if (b ==
     TARGET)
                     System.out.print(
    "Joy!"
    );
            }

        }

    }

    遺憾的是,它根本就通不過編譯。常量聲明有問題,編譯器會告訴你問題所在:0x90對于byte類型來說不是一個有效的數(shù)值。如果你想下面這樣訂正該聲明,那么程序?qū)⑦\行得非常好:
    private static final byte TARGET = (byte)0x90;
    總之,要避免混合類型比較,因為它們內(nèi)在地容易引起混亂.為了幫助實現(xiàn)這個目標,請使用聲明的常量替代“魔幻數(shù)字”。你已經(jīng)了解了這確實是一個好主意:它說明了常量的含義,集中了常量的定義,并且根除了重復(fù)的定義。現(xiàn)在你知道它還可以強制你去為每一個常量賦予適合其用途的類型,從而消除了產(chǎn)生混合類型比較的一種根源。

    對語言設(shè)計的教訓(xùn)是byte數(shù)值的符號擴展是產(chǎn)生bug和混亂的一種常見根源。而用來抵銷符號擴展效果所需的屏蔽機制會使得程序顯得混亂無序,從而降低了程序的可讀性。因此,byte類型應(yīng)該是無符號的。還可以考慮為所有的原始類型提供定義字面常量的機制,這可以減少對易于產(chǎn)生錯誤的類型轉(zhuǎn)換的需求



    posted on 2008-01-12 17:26 々上善若水々 閱讀(722) 評論(0)  編輯  收藏 所屬分類: J2SE

    主站蜘蛛池模板: 国产成人精品免费视频大全| AV激情亚洲男人的天堂国语| 暖暖在线视频免费视频| 亚洲熟女乱综合一区二区| 深夜特黄a级毛片免费播放| 免费a在线观看播放| 免费无码一区二区| 国产成人精品曰本亚洲79ren| 一二三四在线观看免费中文在线观看| 亚洲国产精品自在拍在线播放| 日亚毛片免费乱码不卡一区 | 久久精品国产亚洲5555| 国产乱妇高清无乱码免费| 永久亚洲成a人片777777| a毛片久久免费观看| 色噜噜综合亚洲av中文无码| 最近新韩国日本免费观看| 亚洲三级在线视频| 卡1卡2卡3卡4卡5免费视频| 午夜肉伦伦影院久久精品免费看国产一区二区三区 | 免费又黄又爽又猛的毛片| 一个人看的在线免费视频| 香蕉视频在线观看亚洲| 亚洲免费福利在线视频| 亚洲国产成人AV网站| 亚洲日韩精品一区二区三区| 91精品国产免费久久国语麻豆| 亚洲综合精品成人| 亚洲色偷偷综合亚洲AV伊人| 99国产精品视频免费观看| 亚洲国产精品无码第一区二区三区| 亚洲国产精品成人网址天堂| 久久一区二区三区免费播放| 久久亚洲精品国产亚洲老地址| 亚洲国产精品成人AV无码久久综合影院| 嫩草成人永久免费观看| 中文字幕精品三区无码亚洲| 日日噜噜噜噜夜夜爽亚洲精品| 亚洲免费电影网站| 一级做a爰黑人又硬又粗免费看51社区国产精品视| 亚洲真人无码永久在线|