(轉(zhuǎn))DataInputStream類readLong()引起的思考

今天無(wú)意中看了下jdk中的DataInputStream類伊群,然后看到readLong()方法考杉,如下:

private byte readBuffer[] = new byte[8];
public final long readLong() throws IOException {
        readFully(readBuffer, 0, 8);
        return (((long)readBuffer[0] << 56) +
                ((long)(readBuffer[1] & 255) << 48) +
        ((long)(readBuffer[2] & 255) << 40) +
                ((long)(readBuffer[3] & 255) << 32) +
                ((long)(readBuffer[4] & 255) << 24) +
                ((readBuffer[5] & 255) << 16) +
                ((readBuffer[6] & 255) <<  8) +
                ((readBuffer[7] & 255) <<  0));
    }

頓時(shí)覺得很困惑,為什么數(shù)組里的第一個(gè)元素直接進(jìn)行移位運(yùn)算舰始,而后面的都和255進(jìn)行了與運(yùn)算呢崇棠?
當(dāng)時(shí)覺得困惑的原因是因?yàn)閎yte類型轉(zhuǎn)成int類型應(yīng)該不用做任何處理的,后來(lái)查了下資料后獲得了靈感丸卷,找到了原因枕稀。
原因是這樣的,在將輸入流的內(nèi)容讀取到byte數(shù)組時(shí)谜嫉,會(huì)進(jìn)行截?cái)辔馈R驗(yàn)檩斎肓髯x取時(shí),雖然是按byte讀取的沐兰,但是是以int類型返回哆档,且數(shù)據(jù)范圍是1~255,除非到了輸入流結(jié)束時(shí)住闯,返回才是-1瓜浸。所以在將數(shù)據(jù)讀取到byte數(shù)組澳淑,不可避免會(huì)進(jìn)行截?cái)啵瑢?duì)于一般的數(shù)據(jù)可能沒有問(wèn)題插佛,但是對(duì)于255這樣高位以1開頭的數(shù)據(jù)偶惠,會(huì)有問(wèn)題。因?yàn)閖ava都是有符號(hào)數(shù)朗涩,開頭為1代表是負(fù)數(shù)忽孽。這樣,在readLong()里谢床,對(duì)數(shù)據(jù)元素進(jìn)行移位時(shí)兄一,會(huì)默認(rèn)轉(zhuǎn)換成int型,這樣就導(dǎo)致byte型的255轉(zhuǎn)成int型后识腿,高位依舊為1(實(shí)際上代表的是-1了)出革。這樣并不是我們想要的。實(shí)際上需要對(duì)這些元素進(jìn)行無(wú)符號(hào)擴(kuò)展渡讼,也就是高位補(bǔ)0骂束。這就是為什么都要和255做與運(yùn)算的原因。同樣成箫,可以考慮下為什么第一個(gè)元素沒有進(jìn)行與運(yùn)算直接就移位了展箱?其實(shí)答案很簡(jiǎn)單,就是因?yàn)樵谧笠苿?dòng)56位后蹬昌,高位的8位數(shù)字必然是數(shù)組里的第一個(gè)元素混驰。
通過(guò)這個(gè),我們其實(shí)可以做一些無(wú)符號(hào)左移的操作皂贩。

byte[] bytes = new byte[] { (byte) -42 };
        ByteArrayInputStream input = new ByteArrayInputStream(bytes);
        int i = input.read();       
        System.out.println("無(wú)符號(hào)數(shù):" + i);        
        System.out.println("無(wú)符號(hào)二進(jìn)制數(shù):"  + Integer.toBinaryString(i));

另外可以用更簡(jiǎn)單的方式:

byte b = (byte) -42;
        int result = (b & 0xFF);
        System.out.println("無(wú)符號(hào)數(shù):" + result);
        System.out.println("無(wú)符號(hào)二進(jìn)制數(shù):" + Integer.toBinaryString(result)); 

這種方式就用到上面提到的與計(jì)算方式栖榨。

備注:
(long)readBuffer[0] << 56的運(yùn)算順序是先對(duì)readBuffer[0]向上轉(zhuǎn)型為long,然后做移位運(yùn)算明刷。
對(duì)于byte,short類型的變量婴栽,他們的值域是包括正負(fù)的,所以要得到無(wú)符號(hào)的int值就需要和0xff,0xffff做與運(yùn)算辈末,其目的是保留低位同時(shí)高位置零愚争。
對(duì)于char類型的變量,他的值域不包括負(fù)數(shù)本冲,所以直接強(qiáng)轉(zhuǎn)成int型就可以了准脂。
從DataInputStream的readShort()和readUnsignedShort()可以看出,在方法內(nèi)部都用了in.read(),得到了無(wú)符號(hào)的int,然后兩個(gè)int進(jìn)行拼接檬洞。最后如果是要shot值就直接向下轉(zhuǎn)型狸膏,如果是要得到無(wú)符號(hào)值,就返回int添怔。

public final short readShort() throws IOException {
        int ch1 = in.read();
        int ch2 = in.read();
        if ((ch1 | ch2) < 0)
            throw new EOFException();
        return (short)((ch1 << 8) + (ch2 << 0));
    }
public final int readUnsignedShort() throws IOException {
        int ch1 = in.read();
        int ch2 = in.read();
        if ((ch1 | ch2) < 0)
            throw new EOFException();
        return (ch1 << 8) + (ch2 << 0);
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末湾戳,一起剝皮案震驚了整個(gè)濱河市贤旷,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌砾脑,老刑警劉巖幼驶,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異韧衣,居然都是意外死亡盅藻,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門畅铭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)氏淑,“玉大人,你說(shuō)我怎么就攤上這事硕噩〖俨校” “怎么了?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵炉擅,是天一觀的道長(zhǎng)辉懒。 經(jīng)常有香客問(wèn)我,道長(zhǎng)谍失,這世上最難降的妖魔是什么眶俩? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮袱贮,結(jié)果婚禮上仿便,老公的妹妹穿的比我還像新娘。我一直安慰自己攒巍,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布荒勇。 她就那樣靜靜地躺著柒莉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪沽翔。 梳的紋絲不亂的頭發(fā)上兢孝,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音仅偎,去河邊找鬼跨蟹。 笑死,一個(gè)胖子當(dāng)著我的面吹牛橘沥,可吹牛的內(nèi)容都是我干的窗轩。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼座咆,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼痢艺!你這毒婦竟也來(lái)了仓洼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤堤舒,失蹤者是張志新(化名)和其女友劉穎色建,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體舌缤,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡箕戳,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了国撵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片漂羊。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖卸留,靈堂內(nèi)的尸體忽然破棺而出走越,到底是詐尸還是另有隱情,我是刑警寧澤旨指,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布谆构,位于F島的核電站搬素,受9級(jí)特大地震影響熬尺,放射性物質(zhì)發(fā)生泄漏粱哼。R本人自食惡果不足惜揭措,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望躬充。 院中可真熱鬧,春花似錦、人聲如沸妙蔗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)梳杏。三九已至十性,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間霞势,已是汗流浹背愕贡。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像场梆,于是被迫代替她去往敵國(guó)和親或油。 傳聞我的和親對(duì)象是個(gè)殘疾皇子腔彰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 8086匯編 本筆記是筆者觀看小甲魚老師(魚C論壇)《零基礎(chǔ)入門學(xué)習(xí)匯編語(yǔ)言》系列視頻的筆記,在此感謝他和像他一樣...
    Gibbs基閱讀 37,138評(píng)論 8 114
  • 一、Java 簡(jiǎn)介 Java是由Sun Microsystems公司于1995年5月推出的Java面向?qū)ο蟪绦蛟O(shè)計(jì)...
    子非魚_t_閱讀 4,160評(píng)論 1 44
  • 1 關(guān)鍵字 1.1 關(guān)鍵字的概述 Java的關(guān)鍵字對(duì)java的編譯器有特殊的意義,他們用來(lái)表示一種數(shù)據(jù)類型澳盐,或...
    哈哈哎呦喂閱讀 646評(píng)論 0 0
  • 或許我沒有資格說(shuō) 但是我覺得叼耙,自己真的是笨的可以 或許這樣的人就是這樣 亦或許腕窥,只是因?yàn)閷?duì)象是我 呵呵~ 以后還是...
    Look楊雯子閱讀 299評(píng)論 0 0
  • 成長(zhǎng)的路,每一步都算數(shù) 空閑之余筛婉,今天翻看了李笑來(lái)寫在知筆墨上的新生-七年就是一輩子簇爆。雖然只看了幾篇,但是依然不妨...
    岸遠(yuǎn)_水聲微閱讀 169評(píng)論 0 0