一、背景
在Java手寫JVM時,需要讀取 .class 后綴的字節碼文件。當把字節碼文件以 byte[](比特數組)的形式讀取到內存中時,數組前四個字節為 0xCAFEBABE。
如何判斷我讀取的四個字節的值等於 0xCAFEBABE 呢?
二、單個字節轉int
2.1 正確代碼
public class Test {
public static void main(String[] args) {
int ca = (byte)0xca;
int fe = (byte)0xfe;
int ba = (byte)0xba;
int be = (byte)0xbe;
System.out.println(ca);
System.out.println(fe);
System.out.println(ba);
System.out.println(be);
}
}
輸出結果:
-54 -2 -70 -66
2.2 錯誤示例
int ca = 0xca; // 值為 202
2.3 錯誤原因分析
0xca 轉化為二進制為 11001010
int 型占4個字節:
| 十進制 | 二進制(雙字) |
|---|---|
| -54 | 1111 1111 1111 1111 1111 1111 1100 1010 |
| 202 | 0000 0000 0000 0000 0000 0000 1100 1010 |
表格中數據的正確性,可以借助 Windows 系統的計算器來表示:
長度占1個字節的byte轉化為長度為4個字節的int,高位補充和符號位相同的值,可以保持值的不變。
如果是負數,符號位為1,擴展位數時,高位補1:
| 負數 | 原碼 | 補碼 | 擴展為32位補碼 | 32位原碼 | 結果 |
|---|---|---|---|---|---|
| -54 | 1011 0110 | 1100 1010 | 1111 1111 1111 1111 1111 1111 1100 1010 | 1000 0000 0000 0000 0000 0000 0011 0110 | -54 |
但是,如果直接聲明為整型,則直接把 1100 1010 作為低8位,剩余高32位全是 0。
三、字節數組轉int
有了第二節的結論,我們這里可以用int來表示字節。
public class Test {
public static void main(String[] args) {
byte[] cafebabe = new byte[]{-54,-2,-70,-66};
int result = toInt(cafebabe);
System.out.println(Integer.toHexString(result));
}
private static int toInt(byte[] bytes) {
int result = 0;
for (int i = 0; i < 4; i++) {
result <<= 8;
result |= bytes[i] & 0xFF;
}
return result;
}
}
輸出結果:
cafebabe
說明這里的 toInt 方法是正確的。


