Java輸出通過InetAddress獲得的IP地址數(shù)組詳細(xì)解析
使用 InetAddress 獲取 IP 地址會(huì)得到一個(gè) byte 數(shù)組
如果你直接輸出這個(gè)數(shù)組,你會(huì)發(fā)現(xiàn) IP 地址中的某些位變成了負(fù)數(shù)
比如 61.135.169.105 會(huì)輸出成 61.-121.-87.105
仔細(xì)看一看,會(huì)發(fā)現(xiàn) 135 + 121 = 256,169 + 87 = 256
-_-! 怎么個(gè)情況!
我首先想到的是 byte 類型向 int 類型轉(zhuǎn)換過程中出現(xiàn)了問題,后來發(fā)現(xiàn),實(shí)際不然
因?yàn)?Java 中沒有 unsigned 類型,所以byte、short、int、long 都是有符號(hào)的,所以根本就不存在隱式類型轉(zhuǎn)換出錯(cuò)的問題。
既然說到了 Java 沒有 unsigned 類型,那么 byte 是 8 位,所以表示范圍為 -127 - 128,而 IP 一個(gè)段的表示范圍為 0 - 255,終于找到了不對(duì)勁的地方了
IP 的一個(gè)段是一個(gè) unsigned byte,這樣一個(gè) unsigned byte 存入一個(gè) signed byte 中當(dāng)然會(huì)導(dǎo)致一些問題出現(xiàn)
分析一下:
35 的二進(jìn)制編碼為 1000 0111,最高位置為 1
由于 byte 被認(rèn)為是 unsigned byte,所以最高位的 1 將會(huì)被解釋為符號(hào)位,另外 Java 中存儲(chǔ)是按照補(bǔ)碼存儲(chǔ),所以 1000 0111 會(huì)被認(rèn)為是補(bǔ)碼形式,轉(zhuǎn)換成原碼便是 1111 0001,轉(zhuǎn)換成十進(jìn)制數(shù)便是 -121。
再看,65 的二進(jìn)制編碼為 0100 0001,由于小于 128,所以沒有將最高位置 1,0100 0001 的補(bǔ)碼還是 0100 0001,所以 65 不變。
分析這么多,這個(gè)問題的解決方法其實(shí)很簡(jiǎn)單,將 byte 變量與 0xFF 按位與即可,過程中 byte 會(huì)隱式類型轉(zhuǎn)換為 int,當(dāng)與 0xFF 按位與的時(shí)候,會(huì)將除了低 8 位的其他位全部置 0,這樣一來便將符號(hào)擴(kuò)展的那些高位清除掉了。
最后附上一個(gè)自己寫的通用函數(shù),用來將整型變量的二進(jìn)制編碼輸出
/**
* 將整型變量的二進(jìn)制編碼形式輸出
* @param n 整型變量
* @param size 整型的二進(jìn)制長(zhǎng)度,可使用類似 Short.SIZE 獲得
* @return 二進(jìn)制編碼字符串
*/
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();
}
相關(guān)文章
SpringBoot?整合數(shù)據(jù)源的具體實(shí)踐
本文主要介紹了SpringBoot?整合數(shù)據(jù)源的具體實(shí)踐,利用?Spring?Boot?的自動(dòng)配置和簡(jiǎn)化的注解來簡(jiǎn)化數(shù)據(jù)源配置工作,從而更專注于應(yīng)用程序的業(yè)務(wù)邏輯開發(fā),感興趣的可以了解一下2023-11-11
java自定義注解驗(yàn)證手機(jī)格式的實(shí)現(xiàn)示例
這篇文章主要介紹了java自定義注解驗(yàn)證手機(jī)格式的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
解讀@NoArgsConstructor,@AllArgsConstructor,@RequiredArgsConstr
這篇文章主要介紹了解讀@NoArgsConstructor,@AllArgsConstructor,@RequiredArgsConstructor的區(qū)別及在springboot常用地方,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12
基于JavaMail實(shí)現(xiàn)簡(jiǎn)單郵件發(fā)送
這篇文章主要為大家詳細(xì)介紹了基于JavaMail實(shí)現(xiàn)簡(jiǎn)單郵件發(fā)送,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08

