亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Java 與無符號那些事兒

2019-11-14 22:16:49
字體:
來源:轉載
供稿:網友
java 與無符號那些事兒

最近在使用 Java 作為 WebSocket 客戶端連接 Node.js 的 WebSocket 服務器的時候,由于使用的客戶端庫比較老,所以遇到了字節符號的問題,上網查了一下,看到這篇文章寫的很有意思,就翻譯一下。

原文地址:http://www.darksleep.com/player/JavaAndUnsignedTypes.html

原文作者:Sean R. Owens

以下是正文


Java 中的無符號類型是怎么回事兒?

在 C 和 C++ 這樣的語言中,都提供了不同長度的整數類型:char, short, int, long (實際上,char 并不是真正的整數,但是你可以把它當成整數來用。在實際應用場景中,很多人在 C 語言中用 char 來存儲較小的整數)。在大部分的 32 位操作系統上,這些類型分別對應 1 字節,2 字節,4 字節和 8 字節。但是需要注意的是,這些整數類型所對應的字節長度在不同的平臺上是不一樣的。相對而言,由于 Java 是針對跨平臺來設計的,所以無論運行在什么平臺上,Java 中的 byte 永遠是 1 字節,short 是 2 字節,int 是 4 字節,long 是 8 字節。

C 語言中的整數類型都提供了對應的“無符號”版本,但是 Java 中就沒有這個特性了。我覺得 Java 不支持無符號類型這個事兒實在是太不爽了,你想想,大量的硬件接口、網絡協議以及文件格式都會用到無符號類型?。↗ava 中提供的 char 類型和 C 中的 char 有所不同,在 Java 中,chat 是用 2 個字節來表示 Unicode 值,在 C 中,char 是用 1 個字節來表示 ASCII 值。雖然可以在 Java 中把 char 當做無符號短整型來使用,用來表示 0 到 2^16 的整數。但是這樣來用可能產生各種詭異的事情,比如當你要打印這個數值的時候實際上打印出來的是這個數值對應的字符而不是這個數值本身的字符串表示)。

那么,如何應對 Java 中無符號類型的缺失?

好吧,對于我給出的這種方案,你可能會不喜歡……

答案就是:使用比要用的無符號類型更大的有符號類型。

例如:使用 short 來處理無符號的字節,使用 long 來處理無符號整數等(甚至可以使用 char 來處理無符號短整型)。確實,這樣看起來很浪費,因為你使用了 2 倍的存儲空間,但是也沒有更好的辦法了。另外,需要提醒的是,對于 long 類型變量的訪問不是原子性操作,所以,如果在多線程場景中,你得自己去處理同步的問題。

如何以無符號的形式存儲和讀取數據?

如果有人從網絡上給你發送了一堆包含無符號數值的字節(或者從文件中讀取的字節),那么你需要進行一些額外的處理才能把他們轉換到 Java 中的更大的數值類型。

還有一個就是字節序問題。但是現在我們先不管它,就當它是“網絡字節序”,也就是“高位優先”,這也是 Java 中的標準字節序。

從網絡字節序中讀取

假設我們開始處理一個字節數組,我們希望從中讀取一個無符號的字節,一個無符號短整型和一個無符號整數。

short anUnsignedByte = 0; char anUnsignedShort = 0; long anUnsignedInt = 0; int firstByte = 0; int secondByte = 0; int thirdByte = 0; int fourthByte = 0; byte buf[] = getMeSomeData(); // Check to make sure we have enough bytes if(buf.length < (1 + 2 + 4)) doSomeErrorHandling(); int index = 0; firstByte = (0x000000FF & ((int)buf[index])); index++; anUnsignedByte = (short)firstByte; firstByte = (0x000000FF & ((int)buf[index])); secondByte = (0x000000FF & ((int)buf[index+1])); index = index+2; anUnsignedShort = (char) (firstByte << 8 | secondByte); firstByte = (0x000000FF & ((int)buf[index])); secondByte = (0x000000FF & ((int)buf[index+1])); thirdByte = (0x000000FF & ((int)buf[index+2])); fourthByte = (0x000000FF & ((int)buf[index+3])); index = index+4; anUnsignedInt = ((long) (firstByte << 24                         | secondByte << 16                         | thirdByte << 8                         | fourthByte))                         & 0xFFFFFFFFL;

好吧,現在看起來有一點兒復雜。但是實際上很直觀。首先,你看到很多這樣的東東:

0x000000FF & (int)buf[index]

首先,把有符號的 byte 提升成 int 類型,然后對這個 int 進行按位與操作,僅保留最后 8 個比特位。因為 Java 中的 byte 是有符號的,所以當一個 byte 的無符號值大于 127 的時候,表示符號的二進制位將被設置為 1(嚴格來說,這個不能算是符號位,因為在計算機中數字是按照補碼方式編碼的),對于 Java 來說,這個就是負數。當將負數數值對應的 byte 提升為 int 類型的時候,0 到 7 比特位將會被保留,8 到 31 比特位會被設置為 1。然后將其與 0x000000FF 進行按位與操作來擦除 8 到 31 比特位的 1。上面這句代碼可以簡短的寫作:

0xFF & (int)buf[index]

Java 自動填充 0xFF 的前導的 0 ,并且在 Java 中,位操作符 & 會導致 byte 自動提升為 int。

接下來你看到的是很多的按位左移運算符 <<。 這個操作符會對左操作數按位左移右操作數指定的比特位。所以,如果你有一個 int foo = 0x000000FF,那么 foo << 8 會得到 0x0000FF00,foo << 16 會得到 0x00FF0000。

最后是按位或操作符 |。假設你現在把一個無符號短整型的 2 個字節加載到了對應的整數中,你會得到 0x000000120x00000034 兩個整數?,F在你把第一個字節左移 8 位得到 0x000012000x00000034,然后你需要把他們再拼合回去。所以需要進行按位或操作。0x00001200 | 0x00000034 會得到 0x00001234,這樣就可以存儲到 Java 中的 char 類型。

這些都是基礎操作。但是對于無符號 int,你需要把它存儲到 long 類型中。其他操作和前面類似,只是你需要把 int 提升為 long 然后和 0xFFFFFFFFL 進行按位與操作。最后的 L 用來告訴 Java 請把這個常量視為 long 來處理。

向網絡寫入字節序

假設現在我們要把上面步驟中我們讀取到的數值寫入到緩沖區。我們當時是按照無符號 byte,無符號 short 和無符號 int 的順序讀取的,現在,甭管什么原因吧,我們打算按照無符號 int,無符號 short 和無符號 byte 的順序來寫出。

buf[0] = (anUnsignedInt & 0xFF000000L) >> 24; buf[1] = (anUnsignedInt & 0x00FF0000L) >> 16; buf[2] = (anUnsignedInt & 0x0000FF00L) >> 8; buf[3] = (anUnsignedInt & 0x000000FFL); buf[4] = (anUnsignedShort & 0xFF00) >> 8; buf[5] = (anUnsignedShort & 0x00FF); buf[6] = (anUnsignedByte & 0xFF);
字節序到底是怎么回事兒?這是什么意思?我需要關注嗎?以及,網絡字節序什么樣的?

Java 中所使用的“高位優先”字節序又被稱為“網絡字節序”。Intel x86 處理器是“低位優先”字節序(除非你在上面運行 Java 程序)。x86 系統創建的數據文件通常是(但不是必須的)低位優先的,而 Java 程序創建的數據文件通常是(但不是必須的)高位優先的。任何系統都可以按照自己需要的字節序來輸出數據。

字節序是什么意思?

“字節序”是指計算機是按照何種順序在內存中存儲數值的。常見的無非是高位優先和低位優先兩種模式。你當然需要關注字節序的問題了,否則,如果你按照高位優先的字節序去讀取一個低位優先字節序存儲的數據文件,很可能就只能得到亂七八糟的數據了,反之亦然。

任何數值,無論是何種表達方式,比如 5000,000,007 或者它的 16 進制格式 0x1DCD6507,都可以看做是數字字符串。對于一個數字字符串,我們可以認為它有開始(最左),有結束(最右)。在英語中,第一個數字就是最高位數字,例如 5000,000,007 中的 5 實際上表示的是 500,000,000。最后一位數字是最低位數字,例如 500,000,007 中的 7 對應的值是 7

當我們說到字節序的時候,我們是參照我們寫數字時候的順序。我們總是從高位開始寫,然后是次高位,直到最低位,是不是這樣啊?

在上面的例子中,數值 500,000,007,對應 16 進制表示方式是 0x1DCD6507,我們把它分成 4 個獨立的字節:0x1D, 0xDC, 0x650x07,對應 10 進制的值 29, 205, 101 和 7。最高位字節 29 表示 29 *256 * 256 * 256 = 486539264,接下來是 205,表示 205 * 256 * 256 = 13434880,然后是 101,表示 101 * 256 = 25856,最后一個 7 就是 7 * 1 = 7。它們的值:

486539264 + 13434880 + 25856 + 7 = 500,000,007

當計算機在它的內存中存儲這 4 個字節的時候,假設存儲到內存的地址是 2056, 2057, 2058 和 2059。那么問題來了:到底在哪個內存地址上存儲哪個字節呢?它可能是在地址 2056 存儲 29, 2057 存儲 205,2058 存儲 101,2059 存儲 7,就像你寫下這個數字的順序一樣,我們稱之為高位優先。但是,其他的計算機架構可能是在 2056 存儲 7,2057 存儲 101, 2058 存儲 205, 2059 存儲 29,這樣的順序我們稱之為低位優先。

針對 2 個字節的以及 8 個字節的存儲方式,也是同樣的。最高位字節稱為 MSB,最低位字節稱為 LSB。

好吧,那么我為什么要關心字節序的問題?

這個視情況而定了。通常情況下你不需要關心這個問題。無論你在什么平臺運行 Java 程序,它的字節序都是一樣的,所以你就無需關心字節序的問題。

但是,當你要處理其他語言產生的數據呢?那么,字節序就是一個大問題了。你必須得保證你按照數據被編碼的順序來進行解碼,反之亦然。如果你足夠幸運,通常在 API 或者協議規范、文件格式說明中找到關于字節序的說明。如果不巧……祝你好運吧!

最重要的是,你需要清晰的了解你所使用的字節序是什么樣的以及你需要處理的數據的字節序是什么樣的。如果二者不同,你需要進行額外的處理來保證正確性。還有就是,如果你需要處理無符號數值,你需要確保將正確的字節放到對應 integer/short/long 類型的正確位置。

網絡字節序又是什么?

當設計 ip 協議的時候,高位優先字節序被設計為網絡字節序。在 IP 報文中德數值類型都是按照網絡字節序存儲的。產生報文的計算機所使用的字節序稱為“宿主機字節序”,可能和網絡字節序一樣,也可能不一樣。和網絡字節序一樣,Java 中的字節序是高位優先的。

為什么沒有無符號類型?

為什么 Java 不提供無符號類型呢?好問題!我也常常覺得這個事情非常詭異,尤其是當時已經有很多網絡協議都使用無符號類型了。在 1999 年,我在 Web 上也找了很久(那個時候 google 還沒有這么棒),因為我總是覺得這事兒不應該是這樣。直到有一天我采訪 Java 發明者中的一位(是 Gosling 嗎?不太記得了,要是我保存了當時的網頁就好了),這位設計者說了一段話,大意是:“嘿!無符號類型把事情搞復雜了,沒有人真正需要無符號類型,所以我們把它趕出去了”。

這里有一個頁面,是記錄了一次對 James Gosling 的采訪,看看能否收到一些啟發:

http://www.gotw.ca/publications/c_family_interview.htm

問:程序員經常討論使用“簡單語言”編程的優點和缺點。你怎么看待這個問題?你覺得 C/C++/Java 算是簡單語言嗎?

Ritchie: 略

Stroustrup:略

Gosling:作為一個語言設計者,我不太理解所謂的“簡單”結束了是什么意思,我希望 Java 開發者把這個概念留在他自己腦海里就好啦。舉例來說,按照那個定義,Java 不算是簡單語言。實際上很多語言都會在極端案例下完蛋,那些極端案例是人們都不會理解的。你去問 C 語言開發人員關于無符號的問題,你很快就會發現沒有幾個 C 語言開發人員真正理解無符號類型到底發生了些什么,什么是無符號運算。這些事情讓 C 語言變得復雜。我覺得 Java 語言是非常簡單的。

另外,參考:

http://www.artima.com/weblogs/viewpost.jsp?thread=7555

Oak 往事……

by Heinz Kabutz

2003 年 7 月 15

為了豐富我對 Java 歷史的了解,我開始研究 Sun 的網站,無意間發現了 Oak 0.2 的語言規范書。Oak 是 Java 語言最早使用的名稱,這份文檔算是現存的最古老的關于 Oak 的文檔了。

……

無符號整數(3.1 節)

規范書說:“8 比特,16 比特,32 比特,64 比特的,這 4 種不同寬度的整數類型都是有符號的,除非在前面加上 unsigned 修飾符”。

在側欄中又說:“無符號類型尚未實現;可能永遠也不會實現了?!?好吧,就是這樣了。

Oak 語言規范可以從 https://duke.dev.java.net/green/OakSpec0.2.ps 下載 PostScript 版本,或者從 http://www.me.umn.edu/~shivane/blogs/cafefeed/resources/14-jun-2007/OakSpec0.2.zip 下載壓縮的 PDF 版本。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久久久有精品国产| 中文字幕日韩综合av| 国产欧美欧洲在线观看| 色综合男人天堂| 国产精品久在线观看| 日本一区二区三区在线播放| www.日韩欧美| 国产mv免费观看入口亚洲| 亚洲国产精品999| 国产日本欧美在线观看| 伊人久久久久久久久久久| 欧美专区日韩视频| 98精品国产高清在线xxxx天堂| 久久久久久久久亚洲| 亚洲人成网站在线播| 亚洲偷熟乱区亚洲香蕉av| 精品亚洲一区二区三区在线播放| 欧美在线精品免播放器视频| 国产午夜一区二区| 国产成人短视频| 国产精品91久久久久久| 91成人在线视频| 欧美激情奇米色| 成人在线精品视频| 欧美性xxxxxxx| 国产美女扒开尿口久久久| 国产精品亚洲美女av网站| 日韩专区在线播放| 日韩女在线观看| 热久久这里只有| 久久国产精品首页| 国产精品在线看| 亚洲美女喷白浆| 亚洲自拍偷拍在线| 成人免费在线网址| 欧美夜福利tv在线| 色爱精品视频一区| 欧美伊久线香蕉线新在线| 亚洲国产精品久久久久| 日韩在线播放一区| 久久91超碰青草是什么| 精品久久久久久久久久久| 日韩av免费看| 北条麻妃99精品青青久久| 国产精品电影在线观看| 91免费看片在线| 亚洲美女视频网站| 5566日本婷婷色中文字幕97| 在线观看日韩视频| 亚洲第一在线视频| 日本亚洲欧洲色| 亚洲天堂影视av| 亚洲第一视频在线观看| 国产丝袜一区二区三区免费视频| 国产福利视频一区二区| 欧美wwwwww| 在线播放日韩欧美| 91免费看视频.| 97国产精品视频| 亚洲a∨日韩av高清在线观看| 91久久嫩草影院一区二区| 久久国产精品电影| 国产成人在线亚洲欧美| 国产91在线高潮白浆在线观看| 日韩av色综合| 亚洲电影免费观看高清| 日本中文字幕不卡免费| 亚洲久久久久久久久久| 色偷偷av一区二区三区乱| 欧美丝袜一区二区三区| 国产丝袜视频一区| 欧美另类69精品久久久久9999| 亚洲嫩模很污视频| 亚洲最大激情中文字幕| 国产精品老女人视频| 亚洲片在线资源| 欧美性xxxx18| 亚洲999一在线观看www| 中文字幕日本精品| 精品国产一区二区三区久久久| 欧美日韩国产精品一区二区三区四区| 美女福利视频一区| 日韩中文字幕在线| 久久精品国产欧美亚洲人人爽| 久久人人97超碰精品888| 成人精品一区二区三区电影免费| 热久久这里只有| 性夜试看影院91社区| 日本一区二区三区四区视频| 国产成人精品av| 中文字幕亚洲激情| 欧美性猛交99久久久久99按摩| 久久精品成人动漫| 国产日韩中文字幕| 久久69精品久久久久久久电影好| 欧美一区三区三区高中清蜜桃| 久久综合伊人77777蜜臀| 夜夜嗨av色一区二区不卡| 精品美女永久免费视频| 亚洲黄色片网站| 日韩免费观看视频| 久久99国产精品久久久久久久久| 亚洲女人初尝黑人巨大| 欧美成人精品h版在线观看| 国产91精品久久久| 亚洲欧美一区二区三区情侣bbw| 亚洲综合在线小说| 国产精品激情自拍| 国产色综合天天综合网| 国产www精品| 亚洲成人av中文字幕| 成人h猎奇视频网站| 日韩美女在线播放| 国产精品一区二区性色av| 日韩中文在线中文网在线观看| 欧美电影免费观看大全| 欧美在线观看网站| 亚洲人成网站777色婷婷| 欧美精品少妇videofree| 91久久在线播放| 国产成人精品久久二区二区91| 在线播放日韩av| 国产综合久久久久久| 精品国偷自产在线| 日韩欧美在线中文字幕| 久久久电影免费观看完整版| 亚洲欧洲偷拍精品| 国产欧美一区二区三区久久| 欧美在线亚洲在线| 欧美激情第99页| 亚洲精品美女在线观看| 久久精品久久久久久国产 免费| 7m第一福利500精品视频| 久久久精品美女| 久久免费视频在线观看| 午夜免费在线观看精品视频| 91日韩在线视频| 91视频8mav| 欧美日韩国产成人在线| 91亚洲国产精品| 欧美激情视频在线免费观看 欧美视频免费一| 日本高清不卡的在线| 国产精品久久77777| 国产福利精品视频| 日韩av网站大全| 国产精品成人在线| 有码中文亚洲精品| 日韩成人激情视频| 成人h视频在线| 九九精品在线播放| 国产精品久久久久久久久| 久久av在线看| 77777亚洲午夜久久多人| 日韩欧美成人免费视频| 中文字幕日韩视频| 国产精品毛片a∨一区二区三区|国| 欧美另类第一页| 日韩美女av在线免费观看| 久久av中文字幕| 国产成人精品在线视频| 91精品国产综合久久香蕉922| 国产成人涩涩涩视频在线观看| 亚洲精品日韩丝袜精品| 亚洲自拍小视频免费观看|