在網路通訊、二進位協定解析、檔案格式處理、加密演算法等場景,Java 基本型別 (byte, short, int, long) 與 byte[] 互轉是核心操作。本文提供一個生產級工具類,涵蓋**大端序 (Big-Endian / Network Byte Order)** 標準轉換、無符號處理、十六進位字串轉換,並解析關鍵位運算原理。
Java 基本型別皆為**有號** (最高位為符號位)。網路傳輸標準採用**大端序**:最高位元組在最低位址。
int value = 0x12345678; // 二進位: 00010010 00110100 01010110 01111000
// 記憶體佈局 (大端序):
byte[0] = (byte) 0x12; // 最高位元組 (MSB) - 無符號 18
byte[1] = (byte) 0x34; // 52
byte[2] = (byte) 0x56; // 86
byte[3] = (byte) 0x78; // 最低位元組 (LSB) - 無符號 120
& 0xFF:將 byte (有號 -128~127) 轉為 **無符號 int (0~255)**,去除符號擴展影響。>> n:算術右移 (保留符號位),用於有號數值位移。>>> n:邏輯右移 (補 0),**處理無符號數值/位元組提取必用**。<< n:左移 (補 0),用於組合位元組。package com.example.util;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public final class DataTypeConverter {
private DataTypeConverter() {} // 工具類禁止實例化
// ============ 基本型別 → byte[] (大端序) ============
/** byte → byte[1] */
public static byte[] toBytes(byte value) {
return new byte[] { value };
}
/** short (16位) → byte[2] */
public static byte[] toBytes(short value) {
return new byte[] {
(byte) ((value >>> 8) & 0xFF), // 高位元組
(byte) (value & 0xFF) // 低位元組
};
}
/** int (32位) → byte[4] */
public static byte[] toBytes(int value) {
return new byte[] {
(byte) ((value >>> 24) & 0xFF),
(byte) ((value >>> 16) & 0xFF),
(byte) ((value >>> 8) & 0xFF),
(byte) (value & 0xFF)
};
}
/** long (64位) → byte[8] */
public static byte[] toBytes(long value) {
return new byte[] {
(byte) ((value >>> 56) & 0xFF),
(byte) ((value >>> 48) & 0xFF),
(byte) ((value >>> 40) & 0xFF),
(byte) ((value >>> 32) & 0xFF),
(byte) ((value >>> 24) & 0xFF),
(byte) ((value >>> 16) & 0xFF),
(byte) ((value >>> 8) & 0xFF),
(byte) (value & 0xFF)
};
}
// ============ byte[] → 基本型別 (大端序) ============
/** byte[1] → byte */
public static byte toByte(byte[] bytes, int offset) {
return bytes[offset];
}
/** byte[2] → short (有號) */
public static short toShort(byte[] bytes, int offset) {
return (short) (
((bytes[offset] & 0xFF) << 8) |
((bytes[offset + 1] & 0xFF))
);
}
/** byte[2] → int (無符號 short, 0~65535) */
public static int toUnsignedShort(byte[] bytes, int offset) {
return ((bytes[offset] & 0xFF) << 8) |
((bytes[offset + 1] & 0xFF));
}
/** byte[4] → int (有號) */
public static int toInt(byte[] bytes, int offset) {
return ((bytes[offset] & 0xFF) << 24) |
((bytes[offset + 1] & 0xFF) << 16) |
((bytes[offset + 2] & 0xFF) << 8) |
((bytes[offset + 3] & 0xFF));
}
/** byte[4] → long (無符號 int, 0~4294967295) */
public static long toUnsignedInt(byte[] bytes, int offset) {
return ((((long) bytes[offset] & 0xFF) << 24) |
(((long) bytes[offset + 1] & 0xFF) << 16) |
(((long) bytes[offset + 2] & 0xFF) << 8) |
(((long) bytes[offset + 3] & 0xFF))) & 0xFFFFFFFFL;
}
/** byte[8] → long (有號) */
public static long toLong(byte[] bytes, int offset) {
return ((((long) bytes[offset] & 0xFF) << 56) |
(((long) bytes[offset + 1] & 0xFF) << 48) |
(((long) bytes[offset + 2] & 0xFF) << 40) |
(((long) bytes[offset + 3] & 0xFF) << 32) |
(((long) bytes[offset + 4] & 0xFF) << 24) |
(((long) bytes[offset + 5] & 0xFF) << 16) |
(((long) bytes[offset + 6] & 0xFF) << 8) |
(((long) bytes[offset + 7] & 0xFF)));
}
// ============ 便利方法:ByteBuffer 版 (自動處理位序、邊界檢查) ============
/** 使用 ByteBuffer 寫入 int (預設大端序) */
public static byte[] toBytesBB(int value) {
return ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN).putInt(value).array();
}
/** 使用 ByteBuffer 讀取 int */
public static int toIntBB(byte[] bytes, int offset) {
return ByteBuffer.wrap(bytes, offset, 4).order(ByteOrder.BIG_ENDIAN).getInt();
}
// ============ 十六進位字串轉換 ============
/** byte → 兩位十六進位字串 (如 0x0A → "0A") */
public static String toHex(byte b) {
return String.format("%02X", b & 0xFF);
}
/** byte[] → 十六進位字串 (可選分隔符) */
public static String toHexString(byte[] bytes, String separator) {
StringBuilder sb = new StringBuilder(bytes.length * 3);
for (int i = 0; i < bytes.length; i++) {
if (i > 0 && separator != null) sb.append(separator);
sb.append(String.format("%02X", bytes[i] & 0xFF));
}
return sb.toString();
}
/** 十六進位字串 → byte[] (支援可選分隔符) */
public static byte[] fromHexString(String hex, String separator) {
String clean = (separator == null) ? hex : hex.replace(separator, "");
if (clean.length() % 2 != 0) throw new IllegalArgumentException("Hex string length must be even");
byte[] bytes = new byte[clean.length() / 2];
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) Integer.parseInt(clean.substring(i * 2, i * 2 + 2), 16);
}
return bytes;
}
// ============ 無符號 byte 處理 ============
/** byte → 無符號 int (0~255) */
public static int unsignedByteToInt(byte b) {
return b & 0xFF;
}
}
import org.junit.Test;
import static org.junit.Assert.*;
public class DataTypeConverterTest {
@Test
public void testIntRoundTrip() {
int[] cases = {0, 1, -1, 127, -128, 32767, -32768, 0x7FFFFFFF, 0x80000000, -123456789};
for (int val : cases) {
byte[] bytes = DataTypeConverter.toBytes(val);
int result = DataTypeConverter.toInt(bytes, 0);
assertEquals(val, result);
}
}
@Test
public void testLongRoundTrip() {
long[] cases = {0L, 1L, -1L, Integer.MAX_VALUE, Integer.MIN_VALUE, 0x7FFFFFFFFFFFFFFFL, 0x8000000000000000L};
for (long val : cases) {
byte[] bytes = DataTypeConverter.toBytes(val);
long result = DataTypeConverter.toLong(bytes, 0);
assertEquals(val, result);
}
}
@Test
public void testUnsignedInt() {
// 0xFFFFFFFF 作為有號 int 是 -1,無符號為 4294967295
byte[] bytes = DataTypeConverter.toBytes(-1); // 全 1
long unsigned = DataTypeConverter.toUnsignedInt(bytes, 0);
assertEquals(0xFFFFFFFFL, unsigned);
}
@Test
public void testHexConversion() {
byte[] data = {0x01, 0x23, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF};
String hex = DataTypeConverter.toHexString(data, " ");
assertEquals("01 23 AB CD EF", hex);
byte[] parsed = DataTypeConverter.fromHexString(hex, " ");
assertArrayEquals(data, parsed);
}
@Test
public void testByteBufferEquivalence() {
int val = 0x12345678;
byte[] manual = DataTypeConverter.toBytes(val);
byte[] bb = DataTypeConverter.toBytesBB(val);
assertArrayEquals(manual, bb);
assertEquals(val, DataTypeConverter.toIntBB(bb, 0));
}
}
| 方法 | 效能 | 可讀性 | 安全性 | 適用場景 |
|---|---|---|---|---|
| 手動位運算 | ⭐⭐⭐⭐⭐ (最快) | ⭐⭐ | ⭐⭐ (需自行檢查邊界) | 極高頻呼叫、嵌入式、協定解析核心路徑 |
| ByteBuffer | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ (內建邊界檢查、位序切換) | 一般業務、可維護性優先、需支援小端序 |
| DataOutputStream | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | 寫入檔案/網路流串流場景 |
byte b = (byte) 0xFF; int i = b; → i == -1。必須用 b & 0xFF 取得 255。b << 24 會先將 byte 提升為 int 再位移,若 b 為負數會符號擴展。**必須先 & 0xFF 再位移**:(b & 0xFF) << 24。if (bytes.length < offset + 4) throw new IllegalArgumentException(...)。short 2 字節、int 4 字節、long 8 字節,切勿混用。掌握位元組與基本型別轉換的位運算本質,是處理二進位協定、高效能序列化、硬體介接的核心技能。建議專案中**統一封裝工具類**,優先使用 ByteBuffer 保證正確性與可維護性,僅在經效能分析確認的熱點路徑改用手動位運算優化。