java的中文到底占几个字节?

查了一大堆,糊里糊涂的。现在知道以下几点:

  • java采用unicode编码,占两个字节,编码范围是0x0000到0xFFFF,但一共才65536个数,怎么可能表达世界上所有语言文字呢,于是又冒出来一个增补码,占4个字节,范围是0x100000到0x10FFFF。
    那么现在假设有一个中文,范围超出了65535,那么它到底是怎么编码的,占几个字节,是几个char?

阅读 24.3k
5 个回答
public static void main(String[] args) throws Exception{
    System.out.println("?".getBytes().length); // \u29100
    System.out.println("?".toCharArray().length);
    System.out.println("?".toCharArray()[0]);
    System.out.println("?".toCharArray()[1]);
    System.out.println("中".getBytes().length); // \u4E2D
    System.out.println("中".toCharArray().length);
}

输出:

4
2
?
?
3
1

自己测一下就明白了吧,“?”这个字就是你说的超过65535的汉字,在你的eclipse可能显示不出,你用eclipse的默认字体就能看到。

java虚拟机内部使用UTF-16来表示字符:

中:
UTF-16 : 4E2D

?:
UTF-16 : D864 DD00

但是一个char实际上是一个16位整数,最多只能表示65536(Character.MAX_VALUE==65535)个字符,所以“中”(2个byte==16位)是一个字符,而“?”(4个byte==32位)是两个字符。既然这么说为什么"中".getBytes().length输出3呢?前面我们讲的是JVM内部的表达方式, 我写的这个程序的源文件是UTF-8编码的,UTF-8中一个中文字符是3个字节,不管你的java源代码用什么编码java编译器都会将其映射到UTF-16。
下面我们再写一个例子,这次的源代码我们尝试转成GBK试试:
图片描述

为什么转不了?因为GBK不支持“?”,去掉不支持再转成GBK再运行:

public static void main(String[] args) throws IOException {
     System.out.println("中".getBytes().length); // \u4E2D
     System.out.println("中".toCharArray().length);
}

输出

2
1

如果楼主非要去追个究竟,我建议你下这篇文章

通常我们会设置编码格式为UTF-8,中文在java中一个汉字表示两个字符,3个字节

    public static void main(String[] args) {
        String str = "测试";
        System.out.println(str.getBytes().length);
    }

输出: 6
对于不同的编码格式下所占用的字节数,可参考博客:
不同的编码格式下所占用的字节数

UTF-8三个
GBK两个

你的问题痛点只有一个,混淆了unicode编码字符集和char。java采用unicode编码字符集、utf
-16字符编码表,并不是使用char。char只是一种类型,和int一样。(int只有21亿个,为什么java能表示long长的数字,因为有long型啊)
unicode编码字符集一共有111万多个字符,utf常用有3种,java采用utf-16。wiki的原话

UTF-16 is used internally by systems such as[Microsoft Windows](https://en.wikipedia.org/wiki/Microsoft_Windows "Microsoft Windows"), the[Java programming language](https://en.wikipedia.org/wiki/Java_programming_language "Java programming language")and[JavaScript](https://en.wikipedia.org/wiki/JavaScript "JavaScript")/ECMAScript. It is also often used for[plain text](https://en.wikipedia.org/wiki/Plain_text "Plain text")and for word-processing data files on MS Windows. It is rarely used for files on Unix/Linux or[macOS](https://en.wikipedia.org/wiki/MacOS "MacOS").

utf-16可以表示所有的unicode,111万多个,并且utf-16编码采用2个或者4个 16进制数字表示。为什么,你可以看看wiki了解一下。
char只表示常用的字符,确实是6万多个。还有上面的答案“?”是包含在char中,整型大概是63000多。

还有string.getBytes()是用于获取输出的字节,并不是内部jvm储存的字节,有多个重载,默认的字符集和一个jvm参数息息相关: -Dfile.encoding=UTF-8。一般从IDEA启动程序都是显式设置这个参数。

(感谢评论区提醒)
整理自 —— https://www.jianshu.com/p/092...

在数据存储层面,一个中文字符确实是按照UTF-8的规定,以3个字节的方式保存在文件中
但是当中文字符被读到JVM内存中,该字符会被转为UTF-16,并以2个字节的方式保存在JVM内存中
简单来说就是:在UTF-8文件中,中文字符以UTF-8进行存储,但是读到JVM内存中时,会转换成UTF-16进行存储
所以由于char的长度是2个字节,因此char类型无法表示罕见中文字符

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题