核心场景
- 16进制字符串 → 字节数组:将
"48656C6C6F"转换为字节数组[72, 101, 108, 108, 111]。 - 字节数组 → 16进制字符串:将字节数组
[72, 101, 108, 108, 111]转换为"48656C6C6F"。
使用 java.lang.Integer 和 java.lang.String (基础方法)
这是最基础的方法,适用于单个字节的转换,但需要手动处理循环和格式化。

字节 → 16进制字符串
将一个字节(byte)转换为两位的16进制字符串。
public class HexUtils {
/**
* 将单个字节转换为两位的16进制字符串
* @param b 字节
* @return 16进制字符串 ( 0x0A -> "0A")
*/
public static String byteToHex(byte b) {
// Integer.toHexString() 会将 byte (有符号) 提升为 int (有符号)
// 对于负数,它会得到类似 "ffffffa5" 的结果,所以需要与 0xFF 进行与运算
// 来确保我们只取低8位,并得到一个正数。
return String.format("%02X", b & 0xFF);
}
public static void main(String[] args) {
byte b1 = 10; // 0x0A
byte b2 = -91; // 0xA5 (因为 -91 的二进制补码是 10100101)
System.out.println("Byte 10 to Hex: " + byteToHex(b1)); // 输出: Byte 10 to Hex: 0A
System.out.println("Byte -91 to Hex: " + byteToHex(b2)); // 输出: Byte -91 to Hex: A5
}
}
说明:
b & 0xFF:这是一个非常关键的操作,Java 的byte是有符号的(-128 到 127)。Integer.toHexString(b)在处理负数时会产生不符合预期的结果,通过与0xFF(二进制11111111)进行按位与运算,可以强制将byte转换为一个无符号的int值(0 到 255),从而得到正确的16进制表示。String.format("%02X", ...):%X:将参数格式化为16进制大写字符串。02:确保输出总宽度为2位,如果不足,在前面补0。
16进制字符串 → 字节
将两位的16进制字符串转换为一个字节。
public class HexUtils {
/**
* 将两位的16进制字符串转换为字节
* @param hexStr 16进制字符串 ( "0A")
* @return 字节
*/
public static byte hexToByte(String hexStr) {
// Integer.parseInt() 将16进制字符串解析为int
// 然后强制转换为byte,由于我们输入的是0-255,所以直接转换是安全的。
return (byte) Integer.parseInt(hexStr, 16);
}
public static void main(String[] args) {
String hexStr1 = "0A";
String hexStr2 = "A5";
System.out.println("Hex \"0A\" to Byte: " + hexToByte(hexStr1)); // 输出: Hex "0A" to Byte: 10
System.out.println("Hex \"A5\" to Byte: " + hexToByte(hexStr2)); // 输出: Hex "A5" to Byte: -91
}
}
处理字节数组与16进制字符串的转换 (常用)
在实际应用中,我们通常需要处理整个字节数组,使用上述基础方法,我们可以通过循环来实现,但 Java 提供了更便捷的工具类。

字节数组 → 16进制字符串 (推荐)
使用 javax.xml.bind.DatatypeConverter (JDK 1.6 - 8) 或 java.util.Base64 (JDK 8+)。
方案 A: javax.xml.bind.DatatypeConverter (JDK 8及以下)
这是一个非常方便的旧版 API。
import javax.xml.bind.DatatypeConverter;
public class HexConverter {
public static String bytesToHex(byte[] bytes) {
if (bytes == null) {
return null;
}
// DatatypeConverter 提供了直接转换的方法
return DatatypeConverter.printHexBinary(bytes);
}
public static void main(String[] args) {
String originalString = "Hello, Java!";
byte[] byteArray = originalString.getBytes(); // 默认使用平台编码 (通常是UTF-8)
String hexString = bytesToHex(byteArray);
System.out.println("Original String: " + originalString);
System.out.println("Byte Array to Hex: " + hexString); // 输出: 48656C6C6F2C204A61766121
}
}
方案 B: java.util.Base64 (JDK 8+) (不推荐用于16进制,但常被提及)
注意:Base64 类主要用于 Base64 编码,而不是16进制,虽然它有一些 encodeToString 方法,但不适用于标准的16进制转换,请忽略 Base64 用于16进制的用法。
方案 C: 手动循环 (理解原理)
如果不想依赖外部库,可以自己实现。

public class HexConverter {
public static String bytesToHex(byte[] bytes) {
if (bytes == null) {
return null;
}
StringBuilder sb = new StringBuilder(bytes.length * 2);
for (byte b : bytes) {
sb.append(String.format("%02X", b & 0xFF));
}
return sb.toString();
}
public static void main(String[] args) {
String originalString = "Hello";
byte[] byteArray = originalString.getBytes();
String hexString = bytesToHex(byteArray);
System.out.println("Byte Array to Hex (Manual): " + hexString); // 输出: 48656C6C6F
}
}
16进制字符串 → 字节数组 (推荐)
同样,使用 javax.xml.bind.DatatypeConverter 是最方便的。
方案 A: javax.xml.bind.DatatypeConverter (JDK 8及以下)
import javax.xml.bind.DatatypeConverter;
public class HexConverter {
public static byte[] hexToBytes(String hexString) {
if (hexString == null || hexString.isEmpty()) {
return new byte[0];
}
// DatatypeConverter 提供了直接转换的方法
return DatatypeConverter.parseHexBinary(hexString);
}
public static void main(String[] args) {
String hexString = "48656C6C6F";
byte[] byteArray = hexToBytes(hexString);
// 将字节数组转换回字符串以验证
String originalString = new String(byteArray);
System.out.println("Hex to Byte Array: " + java.util.Arrays.toString(byteArray));
System.out.println("Recovered String: " + originalString); // 输出: Hello
}
}
方案 B: 手动循环 (理解原理)
public class HexConverter {
public static byte[] hexToBytes(String hexString) {
if (hexString == null || hexString.isEmpty()) {
return new byte[0];
}
// 确保字符串长度是偶数
if (hexString.length() % 2 != 0) {
throw new IllegalArgumentException("Invalid hex string: " + hexString);
}
byte[] bytes = new byte[hexString.length() / 2];
for (int i = 0; i < bytes.length; i++) {
// 每次取两个字符
String hexByte = hexString.substring(2 * i, 2 * i + 2);
bytes[i] = (byte) Integer.parseInt(hexByte, 16);
}
return bytes;
}
public static void main(String[] args) {
String hexString = "48656C6C6F";
byte[] byteArray = hexToBytes(hexString);
String originalString = new String(byteArray);
System.out.println("Hex to Byte Array (Manual): " + java.util.Arrays.toString(byteArray));
System.out.println("Recovered String: " + originalString); // 输出: Hello
}
}
总结与最佳实践
| 转换方向 | 推荐方法 (JDK 8) | 推荐方法 (JDK 6-7) | 手动实现 (学习用) |
|---|---|---|---|
| 字节数组 → 16进制字符串 | DatatypeConverter.printHexBinary() |
DatatypeConverter.printHexBinary() |
循环 + String.format("%02X", ...) |
| 16进制字符串 → 字节数组 | DatatypeConverter.parseHexBinary() |
DatatypeConverter.parseHexBinary() |
循环 + Integer.parseInt(hexStr, 16) |
重要提示:DatatypeConverter 的废弃
从 JDK 9 开始,javax.xml.bind 包被标记为废弃,因为它属于 Java EE,而 Java 正在将 Java EE 的功能移到 Jakarta EE 中。
- 在 JDK 9+ 项目中,如果你使用模块系统,可能需要添加
--add-modules java.xml.bind来启用它。 - 长期来看,建议将项目迁移到更新的库,如 Apache Commons Codec,它提供了更稳定和独立的 API。
替代方案:Apache Commons Codec (强烈推荐)
这是一个非常流行且稳定的第三方库,专门用于各种编码和解码。
添加 Maven 依赖
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version> <!-- 使用最新版本 -->
</dependency>
使用 Hex 类
import org.apache.commons.codec.binary.Hex;
public class CommonsHexExample {
public static void main(String[] args) {
String originalString = "Hello, Apache Commons!";
byte[] byteArray = originalString.getBytes();
// 1. 字节数组 -> 16进制字符串
String hexString = Hex.encodeHexString(byteArray);
System.out.println("Byte Array to Hex: " + hexString);
// 输出: 48656C6C6F2C2041706163686520436F6D6D6F6E73
// 2. 16进制字符串 -> 字节数组
byte[] decodedBytes = Hex.decodeHex(hexString);
// 验证
String recoveredString = new String(decodedBytes);
System.out.println("Recovered String: " + recoveredString);
// 输出: Hello, Apache Commons!
}
}
优点:
- API 简洁明了:
encodeHexString和decodeHex。 - 不依赖 Java EE 模块,兼容性好。
- 广泛使用,社区支持好。
最终建议
- 对于新项目:优先考虑使用 Apache Commons Codec,它更现代、更稳定,是行业标准之一。
- 对于旧项目 (JDK 8):如果不想引入新依赖,
javax.xml.bind.DatatypeConverter是一个非常方便的选择。 - 对于学习或面试:理解手动循环实现的过程非常重要,因为它能帮助你掌握底层原理,比如位运算和字符串格式化。
