授课语音

Java字符存储机制

一、Java中的字符存储基础

  1. char 的定义

    • 在 Java 中,char 是一个固定长度的数据类型,占用 2 个字节(16 位)。
    • 它使用 Unicode 字符编码(UCS-2 的子集),直接表示 Unicode 编码中的 基本多文种平面(BMP) 字符,范围是 U+0000U+FFFF
  2. Unicode 与 UTF-8 的区别

    • Unicode 是一种字符集,给每个字符分配唯一的码点。
    • UTF-8 是一种可变长度的编码方式,使用 1 到 4 个字节来编码字符:
      • ASCII 范围字符:1 个字节
      • 大多数常用字符:2~3 个字节
      • 补充字符(超出 BMP 范围的字符):4 个字节

二、Java如何存储 UTF-8 字符

  1. 直接存储 BMP 范围的字符

    • BMP 范围(U+0000U+FFFF)的字符可以直接使用 char 类型存储,因为它们的码点都能用 16 位表示。
    • 例如:
      char ch = 'A';  // 'A' 的 Unicode 码点是 U+0041,直接存储在 char 类型中
      System.out.println(ch);  // 输出 A
      
  2. 存储补充字符

    • 对于超出 BMP 范围的字符(码点大于 U+FFFF,如表情符号 😊,码点为 U+1F60A),无法用单个 char 表示。
    • Java 使用 代理对(Surrogate Pair) 来表示:
      • 高代理项(High Surrogate):码点范围 U+D800U+DBFF
      • 低代理项(Low Surrogate):码点范围 U+DC00U+DFFF
    • 补充字符会被分解成两个 char 类型存储。

    例如:

    public class Utf8Example {
        public static void main(String[] args) {
            // 表情符号 😊 的 Unicode 码点是 U+1F60A
            String emoji = "😊"; // Java 中的字符串支持完整的 UTF-8 字符
    
            // 获取字符的代码点
            int codePoint = emoji.codePointAt(0);
    
            // 分解为代理对
            char highSurrogate = Character.highSurrogate(codePoint);
            char lowSurrogate = Character.lowSurrogate(codePoint);
    
            System.out.println("表情符号的高代理: " + Integer.toHexString(highSurrogate));
            System.out.println("表情符号的低代理: " + Integer.toHexString(lowSurrogate));
        }
    }
    

    输出:

    表情符号的高代理: d83d
    表情符号的低代理: de0a
    
  3. UTF-8 存储与转换

    • 虽然 char 类型无法直接表示 UTF-8 编码的多字节字符,但 Java 提供了工具类(如 StringCharset)支持 UTF-8 的存储和处理。
    • 示例代码:
      import java.nio.charset.StandardCharsets;
      
      public class Utf8Handling {
          public static void main(String[] args) {
              String text = "你好,世界!"; // Unicode 字符串
      
              // 转换为 UTF-8 字节数组
              byte[] utf8Bytes = text.getBytes(StandardCharsets.UTF_8);
              System.out.println("UTF-8 编码的字节长度: " + utf8Bytes.length);
      
              // 从 UTF-8 字节数组还原字符串
              String decodedText = new String(utf8Bytes, StandardCharsets.UTF_8);
              System.out.println("解码后的字符串: " + decodedText);
          }
      }
      

    输出:

    UTF-8 编码的字节长度: 18
    解码后的字符串: 你好,世界!
    

三、总结

  • char 存储的是固定长度的 2 字节 Unicode 编码,无法直接表示所有 UTF-8 字符。
  • 对于超出 BMP 范围的字符,Java 使用代理对将其分解为两个 char 表示。
  • 如果需要完整支持 UTF-8,可以使用 String 类型或相关工具类进行处理。
去1:1私密咨询

系列课程: