Java輸出通過InetAddress獲得的IP地址數(shù)組詳細解析
使用 InetAddress 獲取 IP 地址會得到一個 byte 數(shù)組
如果你直接輸出這個數(shù)組,你會發(fā)現(xiàn) IP 地址中的某些位變成了負數(shù)
比如 61.135.169.105 會輸出成 61.-121.-87.105
仔細看一看,會發(fā)現(xiàn) 135 + 121 = 256,169 + 87 = 256
-_-! 怎么個情況!
我首先想到的是 byte 類型向 int 類型轉(zhuǎn)換過程中出現(xiàn)了問題,后來發(fā)現(xiàn),實際不然
因為 Java 中沒有 unsigned 類型,所以byte、short、int、long 都是有符號的,所以根本就不存在隱式類型轉(zhuǎn)換出錯的問題。
既然說到了 Java 沒有 unsigned 類型,那么 byte 是 8 位,所以表示范圍為 -127 - 128,而 IP 一個段的表示范圍為 0 - 255,終于找到了不對勁的地方了
IP 的一個段是一個 unsigned byte,這樣一個 unsigned byte 存入一個 signed byte 中當然會導致一些問題出現(xiàn)
分析一下:
35 的二進制編碼為 1000 0111,最高位置為 1
由于 byte 被認為是 unsigned byte,所以最高位的 1 將會被解釋為符號位,另外 Java 中存儲是按照補碼存儲,所以 1000 0111 會被認為是補碼形式,轉(zhuǎn)換成原碼便是 1111 0001,轉(zhuǎn)換成十進制數(shù)便是 -121。
再看,65 的二進制編碼為 0100 0001,由于小于 128,所以沒有將最高位置 1,0100 0001 的補碼還是 0100 0001,所以 65 不變。
分析這么多,這個問題的解決方法其實很簡單,將 byte 變量與 0xFF 按位與即可,過程中 byte 會隱式類型轉(zhuǎn)換為 int,當與 0xFF 按位與的時候,會將除了低 8 位的其他位全部置 0,這樣一來便將符號擴展的那些高位清除掉了。
最后附上一個自己寫的通用函數(shù),用來將整型變量的二進制編碼輸出
/**
* 將整型變量的二進制編碼形式輸出
* @param n 整型變量
* @param size 整型的二進制長度,可使用類似 Short.SIZE 獲得
* @return 二進制編碼字符串
*/
public static String printBinary(long n, int size) {
StringBuilder sb = new StringBuilder();
for (int i = size - 1; i >= 0; i--) {
sb.append(n >>> i & 0x01);
if (i % 4 == 0) {
sb.append(" ");
}
}
return sb.toString();
}
相關文章
scala當中的文件操作和網(wǎng)絡請求的實現(xiàn)方法
這篇文章主要介紹了scala當中的文件操作和網(wǎng)絡請求的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-06-06Java?Kryo,Protostuff,Hessian序列化方式對比
這篇文章主要介紹了Java?Kryo,Protostuff,Hessian序列化方式對比,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-07-07在spring boot中使用java線程池ExecutorService的講解
今天小編就為大家分享一篇關于在spring boot中使用java線程池ExecutorService的講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-03-03Java中==運算符與equals方法的區(qū)別及intern方法詳解
這篇文章主要介紹了Java中==運算符與equals方法的區(qū)別及intern方法詳解的相關資料,需要的朋友可以參考下2017-04-04