Java 中char是如何编码的

来源:互联网 发布:mac oracle ide 编辑:程序博客网 时间:2024/06/03 17:33

下面的内容不是我写的,抄的知乎的,看一下人家过来人是怎么理解的,我在这里记录一下,以后想不通的时候过来看看.

题主要区分清楚内码(internal encoding)和外码(external encoding)就好了。内码是程序内部使用的字符编码,特别是某种语言实现其char或String类型在内存里用的内部编码;
外码是程序与外部交互时外部使用的字符编码。“外部”相对“内部”而言;不是char或String在内存里用的内部编码的地方都可以认为是“外部”。例如,外部可以是序列化之后的char或String,或者外部的文件、命令行参数之类的。Java语言规范规定,Java的char类型是UTF-16的code unit,也就是一定是16位(2字节);
char, whose values are 16-bit unsigned integers representing UTF-16 code units (§3.1).
然后字符串是UTF-16 code unit的序列:
The Java programming language represents text in sequences of 16-bit code units, using the UTF-16 encoding.
这样,Java规定了字符的内码要用UTF-16编码。String.getBytes()是一个用于将String的内码转换为指定的外码的方法。无参数版使用平台的默认编码作为外码,有参数版使用参数指定的编码作为外码;将String的内容用外码编码好,结果放在一个新byte[]返回。
题主的例子里,显然外码是UTF-8,那么调用了String.getBytes()之后得到的byte[]只能表明该外码的性质,而无法碰触到String内码的任何特质。可惜UTF-16在Java设计之初还是真的定长编码,后来Unicode涵盖的字符变多了之后UTF-16变成了坑爹的变长编码(一个完整的“字符”是一个code point;一个code point可以对应1到2个code unit;一个code unit是16位),Java也只好跟进。
如果你说的“字符”就是指Java中的char,那好,那它就是16位,2字节。
如果你说的“字符”是指我们用眼睛看到的那些“抽象的字符”,那么,谈论它占几个字节是没有意义的。
具体地讲,脱离具体的编码谈某个字符占几个字节是没有意义的。
就好比有一个抽象的整数“42”,你说它占几个字节?这得具体看你是用byte,short,int,还是long来存它。
字符是同样的道理,如果你想谈“占几个字节”,就要先把编码说清楚。
同一个字符在不同的编码下可能占不同的字节。
就以你举的“字”字为例,“字”在GBK编码下占2字节,在UTF-16编码下也占2字节,在UTF-8编码下占3字节,在UTF-32编码下占4字节。
不同的字符在同一个编码下也可能占不同的字节。
“字”在UTF-8编码下占3字节,而“A”在UTF-8编码下占1字节。(因为UTF-8是变长编码)
而Java中的char本质上是UTF-16编码。而UTF-16实际上也是一个变长编码(2字节或4字节)。
如果一个抽象的字符在UTF-16编码下占4字节,显然它是不能放到char中的。换言之,char中只能放UTF-16编码下只占2字节的那些字符。
而getBytes实际是做编码转换,你应该显式传入一个参数来指定编码,否则它会使用缺省编码来转换。你可以在启动JVM时设置一个缺省编码,否则,会使用所在操作系统环境下的缺省编码。


0 0
原创粉丝点击