無參read返回int類型為何要與上0xff

引言

使用java io 包時,InputStream 類中的有好幾個read()方法,并且返回值也都是int類型,這樣就使得初學者很容易搞混,其實雖然返回值都是int類型,但所表示的意義確是不一樣的

有參 read(byte b[], int off, int len)

先看有參的read方法。
有參的read比較好理解,將讀取到的數(shù)據(jù)寫入字節(jié)數(shù)組(從字節(jié)數(shù)組的指定位置開始寫入)

  • 三個入?yún)?
    • b[] 存儲讀取到的數(shù)據(jù)的字節(jié)數(shù)組
    • off 從目標數(shù)組b[]off位開始寫入,一般都是從0開始
    • len 要讀取的字節(jié)碼長度,一般會是存儲數(shù)組b[]的長度

這里的int類型的返回值是實際讀取的字節(jié)數(shù),如果檢測到無數(shù)據(jù)可讀時會返回 -1

無參 read()

/**
 * 從輸入流讀取下一個字節(jié)的數(shù)據(jù)。返回值為`int類型`,值范圍在`0-255`之間。如果由于到達流
 * 的末尾而沒有可用的字節(jié),則返回`-1`。此方法將一直阻塞,直到輸入數(shù)據(jù)可用、檢測到流的結(jié)
 * 尾或引發(fā)異常為止
 */
public abstract int read() throws IOException;

從輸入流讀取下一個字節(jié)的數(shù)據(jù)。返回值為int類型,值范圍在0-255之間。如果由于到達流的末尾而沒有可用的字節(jié),則返回-1。此方法將一直阻塞,直到輸入數(shù)據(jù)可用、檢測到流的結(jié)尾或引發(fā)異常為止

我們再來看一下這個方法的具體實現(xiàn)

public int read() throws IOException {
    if (eof) {
        return -1;
    }
    temp = new byte[1];
    int n = read(temp, 0, 1);
    if (n <= 0) {
        return -1;
    }
    return temp[0] & 0xff;
}

到這里就很奇怪了,這個方法是返回下一個字節(jié)的數(shù)據(jù),可是為什么要返回一個int類型,而不直接返回 byte 類型?并且返回int類型時還有一個& 0xff操作,為什么還要執(zhí)行這個與操作呢?下面就讓我們好好分析一下,為何要返回int類型,而不直接返回byte類型,以及為何會先執(zhí)行一個& 0xff操作

為何要返回int類型

在讀取字節(jié)時,我們肯定需要一個標識來表示已經(jīng)讀到了字節(jié)流末尾,一般會返回-1來標識,但是如果是返回byte類型,就無法標識是否到了文件末尾。所以單憑這點,這里就不能返回byte類

為何要執(zhí)行與操作& 0xff再返回int類型

上面解釋了為何要返回int類型,可是貌似返回int類型也并沒有解決問題..

看這么一個情況,萬一返回的單個字節(jié)以二進制表示是1111 1111,轉(zhuǎn)換成int類型會高位補符號位1,也就是1111 1111 1111 1111 1111 1111 1111 1111,剛好是-1(Java中數(shù)字是以補碼形式存儲的),所以這里就會產(chǎn)生混亂,我們無法區(qū)分返回-1是不是到了字節(jié)流的末尾

那么這個問題該怎么解決呢?
這里要解決的問題其實就是當還沒有讀到字節(jié)流末尾時不能返回-1,并且二進制字節(jié)流也不能改變
所以這里就加入了& 0xff操作,我們再來看前面返回-1的例子
1111 1111高位自動補1后與上0xff(0000 0000 0000 0000 0000 0000 1111 1111)

1111 1111 1111 1111 1111 1111 1111 1111 & 0000 0000 0000 0000 0000 0000 1111 1111 = 0000 0000 0000 0000 0000 0000 1111 1111

可知執(zhí)行了& 0xff操作后,相當于永遠不會返回負數(shù)了,也就不會存在返回-1和到字節(jié)流末尾返回-1沖突的情況,并且實際的二進制結(jié)構(gòu)也沒有改變,可以說是完美的解決了這個問題。

上面的1111 1111會自動高位補符號位的原因是,當Java檢測到byte要轉(zhuǎn)化或?qū)⒁D(zhuǎn)換成高位類型時,會自動補高位符號位

補符號位

這里再解釋一下補符號位
我們知道byte占一個字節(jié)8位,而int類型占4個字節(jié)32位,所以byte類型向上轉(zhuǎn)換成int類型時需要補符號位,正數(shù)補0,負數(shù)補1。我們補符號位的目的是為了類型轉(zhuǎn)換后大小和符號位都保持不變。

總結(jié)

本篇文章雖然是從IOread方法接入,其實還是跟Java內(nèi)部的編碼格式有關(guān),如數(shù)字在Java內(nèi)存中是以補碼存儲的,數(shù)字類型轉(zhuǎn)換會高位補符號位等等,要徹底搞懂還是要花些時間的。

博客原文地址戳這里

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.編譯程序(1)gcc xx.c,他會默認生成一個a.out的可執(zhí)行文件,在a.out所在目錄,執(zhí)行./a.o...
    萌面大叔2閱讀 1,422評論 0 1
  • 1 關(guān)鍵字 1.1 關(guān)鍵字的概述 Java的關(guān)鍵字對java的編譯器有特殊的意義,他們用來表示一種數(shù)據(jù)類型,或...
    哈哈哎呦喂閱讀 780評論 0 0
  • 1.編譯程序 (1)gcc xx.c,他會默認生成一個a.out的可執(zhí)行文件,在a.out所在目錄,執(zhí)行./a....
    萌面大叔2閱讀 576評論 0 1
  • 什么是 PCM 格式 聲音從模擬信號轉(zhuǎn)化為數(shù)字信號的技術(shù),經(jīng)過采樣、量化、編碼三個過程將模擬信號數(shù)字化。 采樣顧名...
    揚州慢_閱讀 12,777評論 1 19
  • 由于日本的地理位置處在亞歐板塊與太平洋板塊的交界處,也就是環(huán)太平洋火山地震帶中,地殼運動頻繁,多火山地震。但也是這...
    C小姐想太多閱讀 238評論 0 0

友情鏈接更多精彩內(nèi)容