Java 的 String 本身完全支持 Unicode,但显示乱码或断言失败通常源于编码配置错误或对字符/字节/代码点概念混淆;关键在于确保源文件、编译器、运行时及输出终端均统一使用 UTF-8 编码,并在必要时基于 Unicode 代码点而非 char 索引操作字符串。
java 的 `string` 本身完全支持 unicode,但显示乱码或断言失败通常源于编码配置错误或对字符/字节/代码点概念混淆;关键在于确保源文件、编译器、运行时及输出终端均统一使用 utf-8 编码,并在必要时基于 unicode 代码点而非 `char` 索引操作字符串。
在 Java 中处理俄文(如 "наше")、中文、阿拉伯文等非 ASCII 字符串时,String 类型天然支持 UTF-16 编码的 Unicode 字符,因此 substring() 在绝大多数常见场景下(如纯西里尔文、拉丁扩展、汉字等)是完全可用的:
String str = "наше"; String sub = str.substring(0, 2); // ✅ 正确返回 "на" System.out.println(sub); // 输出:на
该代码在标准 UTF-8 环境下可稳定运行(实测验证)。若测试中出现 "" 这类方块乱码,根本原因并非 Java 不支持多语言,而是 I/O 层的编码不匹配,典型场景包括:
- 源代码文件(.java)以 ISO-8859-1 或 GBK 编码保存,但编译器按 UTF-8 解析;
- IDE(如 IntelliJ/Eclipse)未将项目编码设为 UTF-8;
- JVM 启动时未指定 -Dfile.encoding=UTF-8;
- 控制台/终端(Windows CMD、旧版 PowerShell)默认不支持 UTF-8,需手动启用(如 chcp 65001)或改用支持 UTF-8 的终端(如 Windows Terminal、VS Code 终端);
- 日志框架或测试报告工具强制使用错误编码导出文本。
✅ 推荐配置(一劳永逸):
- 源文件保存为 UTF-8(无 BOM);
- IDE 设置 → File Encodings → Project Encoding = UTF-8,Properties Files = UTF-8;
-
编译与运行时添加 JVM 参数:
javac -encoding UTF-8 YourClass.java java -Dfile.encoding=UTF-8 YourClass
-
Maven 用户:在 pom.xml 中显式声明编码:
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties>
⚠️ 重要进阶提示:substring() 的局限性
虽然 "наше".substring(0, 2) 安全有效,但该方法基于 char(UTF-16 code unit)索引,无法正确处理 Unicode 补充字符(Supplementary Characters),例如某些 emoji(如 "\uD83D\uDE00" ?)、古文字或罕见符号——它们由两个 char(代理对,surrogate pair)表示。此时 substring(0, 1) 可能截断代理对,导致无效字符。
✅ 安全操作所有 Unicode 字符的正确方式是使用代码点(Code Point):
立即学习“Java免费学习笔记(深入)”;
String text = "??наше"; // 含 emoji(U+1F468 U+200D U+1F4BB)
// ✅ 基于代码点的安全子串:取前 3 个完整字符(含 emoji)
int[] codePoints = text.codePoints().toArray();
String safeSub = new String(codePoints, 0, Math.min(3, codePoints.length));
System.out.println(safeSub); // ??на
// 或使用更简洁的流式写法(Java 9+):
String safeSub2 = text.codePoints()
.limit(3)
.collect(StringBuilder::new, (sb, cp) -> sb.appendCodePoint(cp), StringBuilder::append)
.toString();? 总结:
- Java String 原生支持多语言,无需“额外添加支持”;
- 乱码 = 编码链路(编辑→编译→运行→显示)某环断裂,优先排查 UTF-8 配置;
- 对常规文字(含西里尔、汉字、拉丁扩展等),substring() 安全可靠;
- 对含 emoji、古文字等补充字符的场景,务必使用 codePoints()、offsetByCodePoints() 等代码点感知 API;
- 永远不要假设 str.length() 等于字符数——它返回的是 UTF-16 code unit 数量,而非 Unicode 字符数(grapheme clusters)。


















