Java中文乱码根本原因是各环节编码不统一:源文件保存、javac编译、JVM运行、终端显示及IO/Web场景的字符集设定若不一致(如UTF-8与GBK混用),就会导致中文转换失真。

Java程序出现中文乱码,根本原因在于字符编码不一致——从源文件保存、编译、运行到控制台或I/O输出,多个环节的编码设定若不统一,中文就会在转换过程中“失真”。最常见的是UTF-8与GBK(或ISO-8859-1)混用。
源文件编码与编译器编码不匹配
Java源文件(.java)本身是文本文件,其保存时使用的编码(如IDE中设置的文件编码)必须和javac编译时默认识别的编码一致。Windows系统下,许多IDE(如老版本Eclipse、记事本)默认用GBK保存,但javac在未指定参数时可能按系统默认(Windows通常是GBK),也可能因JDK版本或环境变量按UTF-8解析,导致编译后字节码中的字符串常量出错。
- 检查方式:用二进制工具或命令行file -i YourClass.java(Linux/macOS)或查看IDE右下角编码标识
- 解决方法:统一设为UTF-8,并显式告诉编译器:javac -encoding UTF-8 YourClass.java
- IDE中务必同步设置:IntelliJ → File → Settings → Editor → File Encodings;Eclipse → Workspace/Project → Text file encoding
JVM运行时默认字符集与系统不一致
Java程序运行时,String内部始终是UTF-16,但涉及字节与字符串互转时(如new String(byte[])、String.getBytes()、文件读写、网络传输),会使用JVM默认字符集(Charset.defaultCharset())。该默认值通常继承自操作系统,但可能被启动参数覆盖或受locale影响。
- 验证当前默认编码:System.out.println(Charset.defaultCharset());
- 强制指定运行时编码:启动JVM时加参数-Dfile.encoding=UTF-8(注意大小写)
- 避免无参构造/方法:不用new String(bytes),改用new String(bytes, "UTF-8");不用str.getBytes(),改用str.getBytes(StandardCharsets.UTF_8)
终端/控制台无法正确显示UTF-8中文
即使Java程序内部编码正确,若终端(cmd、Terminal、IDE Console)本身不支持或未启用UTF-8,输出仍显示为乱码或问号。
立即学习“Java免费学习笔记(深入)”;
- Windows cmd:执行chcp 65001切换到UTF-8代码页(需系统支持),或改用Windows Terminal并设置字体为支持中文的字体(如Microsoft YaHei Consolas Hybrid)
- macOS/Linux Terminal:确保locale设为UTF-8(如en_US.UTF-8),可通过locale命令检查
- IDE内置终端:IntelliJ/Eclipse需单独配置Console Encoding,与项目编码保持一致
Web或IO场景下的隐式编码陷阱
Servlet、Spring Boot响应、文件读写、数据库连接等场景,常存在“默认编码”被忽略的问题:
- Servlet响应:需显式设置response.setCharacterEncoding("UTF-8"),并配合response.setContentType("text/html;charset=UTF-8")
- Spring Boot:在application.properties中添加server.servlet.encoding.charset=UTF-8和server.servlet.encoding.force=true
- 文件读写:避免使用FileReader/FileWriter(它们依赖defaultCharset),改用Files.newBufferedReader(path, StandardCharsets.UTF_8)
- 数据库连接:JDBC URL中加上?useUnicode=true&characterEncoding=UTF-8(MySQL)










