在網絡編程、二進制協議解析、加密算法、硬件通訊等場景中,byte[] 是核心數據載體。Java 中 byte 是有符號 8 位整數(-128~127),但實際業務常需處理無符號字節值(0~255)。本文系統梳理三種字面量寫法、有符號/無符號轉換陷阱、調試可視化技巧與最佳實踐。
// 同一個 byte 數組的三種寫法
byte[] arr1 = { (byte)0b00010110, (byte)0b01010010, (byte)0b10111000 }; // 二進制 (Java 7+)
byte[] arr2 = { 0x16, 0x52, (byte)0xB8 }; // 十六進制
byte[] arr3 = { 22, 82, -72 }; // 十進制(有符號視角)
| 二進制 | 十六進制 | 無符號十進制 | 有符號十進制 (Java byte) |
|---|---|---|---|
| 0001 0110 | 0x16 | 22 | 22 |
| 0101 0010 | 0x52 | 82 | 82 |
| 1011 1000 | 0xB8 | 184 | -72 (184-256) |
核心結論:JVM 內存中存儲的位模式完全相同,只是字面量書寫與調試顯示視角不同。
byte b = (byte) 0xB8; // 184
System.out.println(b); // 輸出 -72
byte 是有符號類型,最高位為符號位// 錯誤:直接用 byte 參與運算會符號擴展
int wrong = b + 10; // -72 + 10 = -62
// 正確:& 0xFF 強制無符號擴展為 int
int correct = (b & 0xFF) + 10; // 184 + 10 = 194
// 通用工具方法
public static int toUnsigned(byte b) {
return b & 0xFF;
}
public static byte fromUnsigned(int val) {
if (val < 0 || val > 255) throw new IllegalArgumentException("超出 byte 無符號範圍");
return (byte) val;
}
| 轉換方向 | 代碼示例 | 說明 |
|---|---|---|
| byte → 十六進制字符串 | String.format("%02X", b & 0xFF) | 大寫、補零兩位 |
| byte[] → Hex 字符串 | Hex.encodeHexString(bytes) (Apache Commons Codec) | 生產首選 |
| Hex 字符串 → byte[] | Hex.decodeHex(hexString) | 自動處理大小寫 |
| byte → 二進制字符串 | String.format("%8s", Integer.toBinaryString(b & 0xFF)).replace(' ', '0') | 補零 8 位 |
// 構建定長二進制報文:魔數(2B) + 版本(1B) + 命令(1B) + 長度(4B) + 體
ByteBuffer buf = ByteBuffer.allocate(1024).order(ByteOrder.BIG_ENDIAN);
buf.putShort((short) 0xABCD); // 魔數
buf.put((byte) 0x01); // 版本
buf.put((byte) 0x03); // 命令
buf.putInt(payload.length); // 長度 (網絡序大端)
buf.put(payload); // 體
byte[] packet = new byte[buf.position()];
System.arraycopy(buf.array(), 0, packet, 0, buf.position());
b & 0xFF 獲取無符號值,是處理二進制數據的黃金法則ByteBuffer、DatagramPacket、Netty ByteBuf 等高級抽象,減少手工位操作