下面我将详细解释这个过程,并提供不同场景下的代码示例和最佳实践。

核心方法:String.getBytes(StandardCharsets.UTF_8)
这是最推荐、最安全、最清晰的方式。
为什么推荐使用 StandardCharsets?
- 明确性:代码
StandardCharsets.UTF_8清楚地表明了你正在使用 UTF-8 字符集,可读性极高。 - 健壮性:它是一个常量,不会为
null,如果你使用字符串字面量(如"UTF-8"),如果拼写错误(例如写成了"UFT-8"),它不会抛出编译错误,只会在运行时抛出UnsupportedCharsetException,这很难调试。 - 性能:
StandardCharsets中的常量在类加载时就会被初始化,避免了每次调用都去查找字符集的开销。
基本转换示例
这是一个最基础的例子,展示如何将一个包含特殊 Unicode 字符(如中文、表情符号)的 Java String 转换为 UTF-8 编码的 byte[]。
import java.nio.charset.StandardCharsets;
public class UnicodeToUtf8Example {
public static void main(String[] args) {
// 1. 定义一个包含 Unicode 字符的字符串
// "你好" 的 Unicode 码点是 \u4f60\u597d
// "😊" (笑脸表情) 的 Unicode 码点是 \ud83d\ude0a
String originalString = "Hello, 世界! 😊";
System.out.println("原始字符串: " + originalString);
System.out.println("字符串长度: " + originalString.length()); // 注意:length() 返回的是 char 数量,一个 BMP 字符算一个,代理对(如表情符号)算两个
// 2. 使用 StandardCharsets.UTF_8 将字符串转换为 UTF-8 字节数组
byte[] utf8Bytes = originalString.getBytes(StandardCharsets.UTF_8);
// 3. 输出结果
System.out.println("UTF-8 字节数组: " + java.util.Arrays.toString(utf8Bytes));
// 4. (可选) 将字节数组转换回字符串,验证转换是否正确
String decodedString = new String(utf8Bytes, StandardCharsets.UTF_8);
System.out.println("从字节数组解码后的字符串: " + decodedString);
System.out.println("转换前后是否一致: " + originalString.equals(decodedString));
}
}
输出结果:
原始字符串: Hello, 世界! 😊
字符串长度: 11
UTF-8 字节数组: [72, 101, 108, 108, 111, 44, 32, -28, -72, -83, -26, -107, -116, 33, 32, -16, -97, -98, -107, -126]
从字节数组解码后的字符串: Hello, 世界! 😊
转换前后是否一致: true
分析:

H,e,l,l,o, , ` ` 等英文字符,在 UTF-8 中占用 1 个字节。世,界等中文字符,在 UTF-8 中占用 3 个字节。-28, -72, -83"世" 的 UTF-8 编码(在 Java 中,byte是有符号的,所以显示为负数)。- (表情符号) 是一个辅助平面字符,由一个“代理对”(Surrogate Pair)组成,在 UTF-8 中占用 4 个字节(
-16, -97, -98, -107)。
其他不推荐的方式(为了完整性了解)
虽然 StandardCharsets.UTF_8 是最佳实践,但你可能会遇到以下两种写法,了解它们的区别很重要。
使用 String.getBytes("UTF-8")
这种方式通过字符串指定字符集名称。
String originalString = "你好";
try {
byte[] utf8Bytes = originalString.getBytes("UTF-8");
System.out.println(java.util.Arrays.toString(utf8Bytes));
} catch (java.io.UnsupportedEncodingException e) {
// 如果系统不支持 "UTF-8" 编码,会抛出此异常
e.printStackTrace();
}
为什么不推荐?
JVM 不支持你指定的字符集名称(例如拼写错误 "UFT-8"),会抛出 UnsupportedEncodingException,虽然 UTF-8 几乎在所有现代 JVM 上都默认支持,但这种写法不够健壮。
使用 String.getBytes(Charset charset)
这是 StandardCharsets.UTF_8 方法的底层实现方式,你需要先从 Charset.forName() 获取 Charset 对象。

String originalString = "你好";
Charset utf8Charset = Charset.forName("UTF-8");
byte[] utf8Bytes = originalString.getBytes(utf8Charset);
System.out.println(java.util.Arrays.toString(utf8Bytes));
为什么不推荐?
这种方式比 StandardCharsets 稍显冗长,Charset.forName() 在每次调用时都会进行查找,虽然性能影响极小,但不如直接使用常量来得简洁高效。
实际应用场景
场景1:将字符串写入文件(UTF-8 编码)
这是最常见的用途之一,确保文件以正确的编码保存。
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class WriteFileWithUtf8 {
public static void main(String[] args) {
String content = "这是要写入文件的中文内容。";
Path path = Paths.get("output.txt");
try (BufferedWriter writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) {
writer.write(content);
System.out.println("文件已成功写入,编码为 UTF-8。");
} catch (IOException e) {
System.err.println("写入文件时出错: " + e.getMessage());
}
}
}
场景2:在 HTTP 响应中设置字符编码
在 Web 开发中,你需要告诉浏览器响应内容使用的是 UTF-8 编码。
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Utf8ResponseServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 1. 设置响应内容类型和字符编码
// 这是最关键的一步,告诉浏览器使用 UTF-8 解码
response.setContentType("text/html; charset=UTF-8");
// 2. 获取输出流并写入内容
// PrintWriter 会自动使用 response.getCharacterEncoding() 指定的编码
PrintWriter out = response.getWriter();
out.println("<html><head><title>测试页面</title></head>");
out.println("<body>");
out.println("<h1>你好,世界!</h1>");
out.println("<p>这是一个使用 UTF-8 编码的中文页面。</p>");
out.println("</body></html>");
}
}
场景3:处理字节数据(如网络传输)
当你需要通过网络发送字符串时,必须将其转换为字节数组。
import java.nio.charset.StandardCharsets;
public class NetworkTransmission {
public static void main(String[] args) {
String message = "服务器响应数据:操作成功";
// 模拟将字符串转换为网络包
byte[] dataPacket = message.getBytes(StandardCharsets.UTF_8);
// ... 在这里通过 Socket 或其他方式发送 dataPacket ...
// 模拟接收方从网络包中读取数据并解码
String receivedMessage = new String(dataPacket, StandardCharsets.UTF_8);
System.out.println("接收到的消息: " + receivedMessage);
}
}
| 方法 | 优点 | 缺点 | 推荐度 |
|---|---|---|---|
getBytes(StandardCharsets.UTF_8) |
最佳实践:代码清晰、健壮、性能高 | 无 | ⭐⭐⭐⭐⭐ (强烈推荐) |
getBytes("UTF-8") |
语法简洁 | 可能抛出 UnsupportedEncodingException |
⭐⭐☆☆☆ (仅在能保证环境时使用) |
getBytes(Charset.forName("UTF-8")) |
灵活 | 代码冗长,性能略低 | ⭐⭐☆☆☆ (不推荐,除非有特殊需求) |
核心要点:
- 始终优先使用
StandardCharsets.UTF_8。 - Java 的
String内部使用 UTF-16 编码,但它提供了非常方便的方法来与其他编码(如 UTF-8)进行转换。 String -> byte[]是编码过程。byte[] -> String是解码过程,解码时必须使用与编码时相同的字符集,否则会出现乱码(例如用 ISO-8859-1 解码 UTF-8 字节)。
