杰瑞科技汇

Java字符到底占几个字节?

这是一个非常经典且重要的问题,答案比“固定几个字节”要复杂一些,答案是:

Java字符到底占几个字节?-图1
(图片来源网络,侵删)

在 Java 中,一个 char 类型在内存中永远占用 2 个字节。

但这背后涉及到了 Java 的设计哲学和字符编码,下面我们来详细解释。


核心答案:char 是 2 字节 (UTF-16)

在 Java 的虚拟机规范中,char 类型被定义为 16 位(bit)的 Unicode 字符,因为 1 字节 = 8 位,

char 在内存中固定占用 2 个字节。

Java字符到底占几个字节?-图2
(图片来源网络,侵删)

这个 char 类型使用的是 UTF-16 编码方案,UTF-16 是一种变长编码,但对于基本多语言平面(BMP)中的字符(包括世界上绝大多数常用的字符,如所有汉字、英文字母、拉丁字母等),UTF-16 就用 2 个字节(16位)来表示。

代码示例

public class CharSize {
    public static void main(String[] args) {
        char a = 'A'; // 英文字符
        char zh = '中'; // 中文字符
        // 使用 Character 类的 SIZE 常量
        System.out.println("A char occupies: " + Character.SIZE + " bits"); // 输出: 16 bits
        System.out.println("A char occupies: " + Character.BYTES + " bytes"); // 输出: 2 bytes
        // 在内存中,无论是什么字符,都占2个字节
        System.out.println("The character 'A' is stored in 2 bytes.");
        System.out.println("The character '中' is stored in 2 bytes.");
    }
}

深入理解:为什么是 UTF-16?

Java 诞生于 1990 年代中期,当时 Unicode 标准正处于从 16 位向 32 位扩展的过渡期,设计者选择了 UTF-16,因为它:

  • 能够用 16 位覆盖当时已知的所有字符(基本多语言平面)。
  • 对于英文字符,UTF-16 和 ASCII 一样,只需 2 个字节,比 UTF-8 的 1 个字节稍大,但处理起来更简单(定长)。
  • 对于 BMP 之外的字符(如一些生僻的古文字或特殊符号),UTF-16 使用“代理对”(Surrogate Pair)机制,即用两个 char(4个字节)来表示一个字符,这在 Java 中是透明的,你仍然操作的是 char 类型。

常见的误区与澄清

“一个中文字符等于两个英文字符,所以一个中文字符占 2 个字节,一个英文字符占 1 个字节。”

这是错误的。 这个说法混淆了 字符的显示宽度字符的存储/编码大小

  • 显示宽度:在某些等宽字体(如终端、代码编辑器)中,一个中文字符确实占据两个英文字符的宽度,这是一种显示特性。
  • 存储大小:在 Java 的 char 类型中,无论 'A' 还是 '中',都严格占用 2 个字节

“Java 字符串是由 char 组成的,所以一个字符串的字节数 = 字符数 × 2。”

这通常是正确的,但有例外。

一个 String 对象在内存中是由 char 数组构成的,所以对于不包含代理对的字符串,其字节数确实是 length() * 2

如果字符串包含了 BMP 之外的字符(,这是一个生僻的汉字),Java 内部会用两个 char 来表示它。String.length() 会返回 2,但这个字符在逻辑上只算 1 个。

// 这个字符 '𠮷' (U+20BB7) 在 BMP 之外
String s = "𠮷"; 
// String.length() 返回的是 char 数组的长度,这里是 2
System.out.println(s.length()); // 输出: 2
// 但它实际上只代表 1 个 Unicode 码点
System.out.println(s.codePointCount(0, s.length())); // 输出: 1
// 如果你想知道字符串在 UTF-16 编码下的确切字节数
byte[] utf16Bytes = s.getBytes(StandardCharsets.UTF_16);
System.out.println("UTF-16 byte length: " + utf16Bytes.length); // 输出: 4 (因为有 BOM 头 + 2个char)

实际应用:如何计算字符串的字节数?

如果你想知道一个 String 在特定编码(如 UTF-8)下占用的字节数,绝对不能简单地用 length() * 2,必须使用 String.getBytes() 方法。

import java.nio.charset.StandardCharsets;
public class StringByteSize {
    public static void main(String[] args) {
        String str = "Hello 你好";
        // 1. 错误的方法:不能直接 length() * 2
        // 这只适用于纯 BMP 字符且不考虑编码的情况
        // System.out.println("Wrong size: " + str.length() * 2); // 14 bytes
        // 2. 正确的方法:使用 getBytes() 指定编码
        // UTF-8 编码下,英文字符占1字节,中文字符占3字节
        byte[] utf8Bytes = str.getBytes(StandardCharsets.UTF_8);
        System.out.println("UTF-8 byte length: " + utf8Bytes.length); // 输出: 11 (5*1 + 2*3 = 11)
        // UTF-16 编码下,英文字符和中文字符都占2字节
        byte[] utf16Bytes = str.getBytes(StandardCharsets.UTF_16);
        // 注意:UTF-16 通常会包含一个 BOM (Byte Order Mark) 头,占用2字节
        // 所以总长度是 2 (BOM) + 7 (字符数) * 2 = 16
        System.out.println("UTF-16 byte length: " + utf16Bytes.length); // 输出: 16
        // GBK 编码下,英文字符占1字节,中文字符占2字节
        byte[] gbkBytes = str.getBytes("GBK");
        System.out.println("GBK byte length: " + gbkBytes.length); // 输出: 9 (5*1 + 2*2 = 9)
    }
}

问题 答案 解释
一个 char 占几个字节? 2 个字节 Java 虚拟机规范规定 char 是 16 位,固定占用 2 字节,使用 UTF-16 编码。
一个中文字符占几个字节? char 中是 2 个字节 存储时,和英文字符一样,都占 2 字节。
如何计算字符串的字节数? 使用 String.getBytes(编码) 字符串的字节数取决于其编码方式(UTF-8, GBK 等),不能简单地用字符数乘以一个固定值。
charString 的关系? Stringchar[] 的封装 String 的底层是 char 数组,但处理字符数量时要注意代理对的情况。

记住这个核心区别:char 是 JVM 内部的固定大小类型(2字节),而字符的存储和传输则取决于具体的编码(如 UTF-8, GBK)。

分享:
扫描分享到社交APP
上一篇
下一篇