太阳不下山 发表于 2021-8-17 11:58:17

详解Java语言中一个字符占几个字节?

题主要区分清楚内码(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内部采用了非utf-16的编码。
另举一例:
java标准库实现的对char与string的序列化规定使用utf-8作为外码。java的class文件中的字符串常量与符号名字也都规定用utf-8编码。这大概是当时设计者为了平衡运行时的时间效率(采用定长编码的utf-16)与外部存储的空间效率(采用变长的utf-8编码)而做的取舍。
首先,你所谓的“字符”具体指什么呢?
如果你说的“字符”就是指 java 中的 char,那好,那它就是 16 位,2 字节。
如果你说的“字符”是指我们用眼睛看到的那些“抽象的字符”,那么,谈论它占几个字节是没有意义的。
具体地讲,脱离具体的编码谈某个字符占几个字节是没有意义的。


就好比有一个抽象的整数“42”,你说它占几个字节?这得具体看你是用 byte,short,int,还是 long 来存它。用 byte 存就占一字节,用 short 存就占两字节,int 通常是四字节,long 通常八字节。当然,如果你用 byte,受限于它有限的位数,有些数它是存不了的,比如 256 就无法放在一个 byte 里了。
字符是同样的道理,如果你想谈“占几个字节”,就要先把编码说清楚。
同一个字符在不同的编码下可能占不同的字节。


就以你举的“字”字为例,“字”在 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 实际是做编码转换,你应该显式传入一个参数来指定编码,否则它会使用缺省编码来转换。


你说“ new string("字").getbytes().length 返回的是3 ”,这说明缺省编码是 utf-8.如果你显式地传入一个参数,比如这样“ new string("字").getbytes("gbk").length ”,那么返回就是 2.
你可以在启动 jvm 时设置一个缺省编码,


假设你的类叫 main,那么在命令行中用 java 执行这个类时可以通过 file.encoding 参数设置一个缺省编码。比如这样:java -dfile.encoding=gbk main这时,你再执行不带参数的 getbytes() 方法时,new string("字").getbytes().length 返回的就是 2 了,因为现在缺省编码变成 gbk 了。当然,如果这时你显式地指定编码,new string("字").getbytes("utf-8").length 返回的则依旧是 3
否则,会使用所在操作系统环境下的缺省编码。


通常,windows 系统下是 gbk,linux 和 mac 是 utf-8.但有一点要注意,在 windows 下使用 ide 来运行时,比如 eclipse,如果你的工程的缺省编码是 utf-8,在 ide 中运行你的程序时,会加上上述的 -dfile.encoding=utf-8 参数,这时,即便你在 windows 下,缺省编码也是 utf-8,而不是 gbk。
由于受启动参数及所在操作系统环境的影响,不带参数的 getbytes 方法通常是不建议使用的,最好是显式地指定参数以此获得稳定的预期行为。
以上所述是小编给大家介绍的java语言中一个字符占几个字节详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对CodeAE代码之家网站的支持!
原文链接:https://blog.csdn.net/h12kjgj/article/details/73496949

文档来源:http://www.zzvips.com/article/180110.html
页: [1]
查看完整版本: 详解Java语言中一个字符占几个字节?