首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 字符編碼根本原理:從源碼到 JVM 內存再到外部系統的完整鏈路

     編輯:Java 相關知識

核心認知:編碼問題存在於兩個邊界

編碼流程圖

  • JVM 內部:統一使用 UTF-16 (char/String 內部表示)。
  • JVM 外部:檔案、網路、資料庫、終端機、瀏覽器——各自可能使用不同編碼 (GBK, UTF-8, ISO-8859-1...)。

亂碼本質:邊界處編碼/解碼不匹配。

階段一:Java 源碼 → Class 文件

  • 源碼編碼:任意 (UTF-8, GBK, Big5...),由 javac -encoding 指定。
  • 編譯器按指定編碼讀取源碼,將字面量轉為 UTF-16 存入 Class 常量池(CONSTANT_String_info)。
  • 結論:無論源碼編碼何種,Class 中字串常量**統一為 UTF-16**。

階段二:JVM 內存中的字串

  • 類加載時按 UTF-16 讀取常量池,String 物件內部為 char[] (UTF-16 代碼單元)。
  • String.getBytes() **不帶參數** 時,使用**平台預設編碼** 將 UTF-16 轉為 byte[] —— **亂碼禍根**。
  • 驗證平台預設編碼:
System.out.println(Charset.defaultCharset()); // Windows 中文版通常輸出 GBK

階段三:外部系統交互的三大邊界

邊界典型場景關鍵原則
檔案 I/OFileReader/Writer, InputStreamReader/Writer**顯式指定 Charset**,勿依賴預設值
網路傳輸HTTP Header, JSON, XML, Protobuf協議規範編碼 (HTTP: Content-Type charset; JSON: 必須 UTF-8)
資料庫JDBC URL, 表/欄位字符集連接字串指定 characterEncoding,表欄位一致

統一編碼策略:中文系統最佳實踐

  1. 源碼統一 UTF-8:IDE、編譯器、版本控制全鏈路 UTF-8(現代標準,支援全字符集)。
  2. JVM 內部無感知:自動 UTF-16,開發者無需干預。
  3. 外部輸出統一 UTF-8:HTTP Response、JSON、XML、檔案寫入、資料庫連接全部 UTF-8。
  4. 特殊舊系統兼容:若必須對接 GBK 系統,在**邊界層** 顯式轉碼:
// 讀取 GBK 檔案 → 內存 String (UTF-16)
String content = new String(Files.readAllBytes(path), "GBK");

// 內存 String → 寫入 GBK 檔案
Files.write(path, content.getBytes("GBK"));

關鍵 API:永遠帶上 Charset 參數

// ✅ 正確
byte[] bytes = string.getBytes(StandardCharsets.UTF_8);
String str = new String(bytes, StandardCharsets.UTF_8);
Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
Writer writer = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);

// ❌ 錯誤:依賴平台預設編碼
byte[] bytes = string.getBytes();
String str = new String(bytes);

避坑指南:UTF-8 ≠ 萬能

  • UTF-8 **無法表示** GB18030 獨有字符(如「鎔」U+9394 在 GB18030 有編碼,UTF-8 也有,但早期 MySQL utf8 只支援 3 字節,需用 utf8mb4)。
  • **系統內部混用編碼是大忌**:有人用 GBK、有人用 UTF-8、有人用 GB18030 → 編譯報錯、運行時亂碼。**專案強制統一 UTF-8**。
  • Ant/Maven 編譯必須設定 <properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties>。

總結

編碼問題不可怕,**可怕的是邊界模糊**。記住:JVM 內部 UTF-16,外部統一 UTF-8,邊界顯式轉碼。這是解決 99% 亂碼問題的黃金法則。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved