详解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 执⾏这个类时可以通过 ding 参数设置⼀个缺省编码。⽐如这样:java -ding=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 中运⾏你的程序时,会加上上述的 -ding=UTF-
8 参数,这时,即便你在 Windows 下,缺省编码也是 UTF-8,⽽不是 GBK。
由于受启动参数及所在操作系统环境的影响,不带参数的 getBytes ⽅法通常是不建议使⽤的,最好是显式地指定参数以此获得稳定的预期⾏为。
以上所述是⼩编给⼤家介绍的Java语⾔中⼀个字符占⼏个字节详解整合,希望对⼤家有所帮助,如果⼤家有任何疑问请给我留⾔,⼩编会及时回复⼤家的。在此也⾮常感谢⼤家对⽹站的⽀持!

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。