如果不指定编码,程序会使用平台默认的编码,这可能会导致在不同操作系统上(如 Windows vs. Linux)得到不同的结果,从而引发难以排查的 Bug。强烈建议始终明确指定字符编码。

下面我将介绍几种最常用和最推荐的方法。
核心方法:String.getBytes(StandardCharsets charset)
这是最推荐、最安全的方法,它来自 Java 1.7+,使用 java.nio.charset.StandardCharsets 枚举,可以确保代码在任何平台上行为一致。
使用 UTF-8 编码(最常用)
UTF-8 是目前互联网上最通用的编码,它可以表示全球几乎所有语言的字符,并且与 ASCII 兼容。在绝大多数情况下,这应该是你的首选。
import java.nio.charset.StandardCharsets;
public class StringToBytesExample {
public static void main(String[] args) {
String originalString = "Hello, 世界!"; // 包含英文字符和中文字符
// 方法一:使用 StandardCharsets.UTF_8 (推荐)
byte[] utf8Bytes = originalString.getBytes(StandardCharsets.UTF_8);
// 打印结果
System.out.println("原始字符串: " + originalString);
System.out.println("UTF-8 字节数组: " + java.util.Arrays.toString(utf8Bytes));
// 输出: [72, 101, 108, 108, 111, 44, 32, -28, -72, -83, -26, -107, -116, 33]
// 'H' -> 72, '世' -> -28, -72, -83 (三个字节)
}
}
使用其他标准编码
StandardCharsets 还提供了其他几种常用的编码。

import java.nio.charset.StandardCharsets;
public class StringToBytesExample {
public static void main(String[] args) {
String originalString = "Hello";
// ISO-8859-1 (Latin-1): 每个字符只占一个字节,不支持中文等复杂字符
byte[] isoBytes = originalString.getBytes(StandardCharsets.ISO_8859_1);
// US-ASCII: 与 ISO-8859-1 基本相同,但范围更小,只支持英文字符
byte[] asciiBytes = originalString.getBytes(StandardCharsets.US_ASCII);
System.out.println("ISO-8859-1 字节数组: " + java.util.Arrays.toString(isoBytes));
System.out.println("US-ASCII 字节数组: " + java.util.Arrays.toString(asciiBytes));
}
}
其他方法(不推荐,但需要了解)
使用 String.getBytes(String charsetName)
这个方法通过传入编码名称(如 "UTF-8")来指定编码,它的缺点是如果编码名称拼写错误,会抛出 UnsupportedEncodingException 异常,需要你手动处理(try-catch)。
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets; // 用于对比
public class StringToBytesExample {
public static void main(String[] args) {
String originalString = "Hello, 世界!";
try {
// 方法二:使用编码名称字符串 (不推荐,因为会抛出异常)
byte[] utf8BytesByName = originalString.getBytes("UTF-8");
System.out.println("使用 'UTF-8' 名称的字节数组: " + java.util.Arrays.toString(utf8BytesByName));
// 如果编码名写错了,会抛出异常
// byte[] errorBytes = originalString.getBytes("UTF-8-ERROR");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
System.err.println("不支持的编码格式!");
}
// 为了对比,看看不用 try-catch 会怎样
// 这段代码在编译时会提示 "unreported exception UnsupportedEncodingException"
// byte[] bytes = originalString.getBytes("GBK");
}
}
为什么不推荐?
现代 Java 开发中,所有常用的编码(UTF-8, ISO-8859-1 等)都在 StandardCharsets 中定义好了,使用它既安全又无需处理异常,是更优的选择。
使用 String.getBytes() (不推荐!)
这个方法不接收任何参数,它会使用 JVM 运行时所在操作系统的默认字符编码。
public class StringToBytesExample {
public static void main(String[] args) {
String originalString = "Hello, 世界!";
// 方法三:使用平台默认编码 (强烈不推荐!)
byte[] defaultBytes = originalString.getBytes();
System.out.println("默认编码的字节数组: " + java.util.Arrays.toString(defaultBytes));
// 在中文Windows上可能是GBK编码,在Linux上可能是UTF-8编码
}
}
为什么不推荐? 这会导致你的代码具有平台相关性,在开发环境(Windows)上运行正常的代码,部署到生产环境(Linux)后可能会因为编码不同而出现乱码或数据损坏。除非你 100% 确定你就是要使用平台默认编码,并且清楚其后果,否则永远不要使用这个方法。

反向操作:byte[] 转 String
将字节数组转换回字符串时,同样需要使用相同的编码,否则会出现乱码。
import java.nio.charset.StandardCharsets;
public class BytesToStringExample {
public static void main(String[] args) {
byte[] utf8Bytes = {72, 101, 108, 108, 111, 44, 32, -28, -72, -83, -26, -107, -116, 33};
// 使用相同的编码 UTF-8 进行解码
String decodedString = new String(utf8Bytes, StandardCharsets.UTF_8);
System.out.println("解码后的字符串: " + decodedString); // 输出: Hello, 世界!
// 错误示范:用错误的编码解码
// String wrongString = new String(utf8Bytes, StandardCharsets.ISO_8859_1);
// System.out.println("错误解码的结果: " + wrongString); // 输出: Hello, ??!
}
}
总结与最佳实践
| 方法 | 描述 | 推荐度 |
|---|---|---|
str.getBytes(StandardCharsets.UTF_8) |
最推荐,明确指定 UTF-8 编码,安全、高效、跨平台。 | |
str.getBytes("UTF-8") |
可以指定编码,但需要处理 UnsupportedEncodingException,代码更冗长。 |
|
str.getBytes() |
使用平台默认编码,极其不推荐,会导致代码行为不可预测,引发乱码。 |
核心要点:
- 始终指定编码:不要依赖平台默认编码。
- 优先使用
StandardCharsets:它提供了类型安全的编码常量,无需处理异常。 - UTF-8 是首选:在处理网络传输、文件存储等通用场景时,UTF-8 是事实上的标准。
- 编解码需一致:将
String转为byte[]时使用的编码,必须与将byte[]转回String时使用的编码完全相同。
