Java中理论说是一个字符(汉字 字母)占用两个字节。但是在UTF-8的时候 new String(“字”).getBytes().length 返回的是3 表示3个字节。
首先要区分清楚内码(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的编码。
“感知”可以是多方面的,例如随机访问某个下标的code unit(String.charAt())应该是O(1)操作,这只有使用UTF-16或者别的“定长”编码才可以做到。注意我这里说的“定长”特指code unit定长,而不是说code point定长。
String.getBytes()是一个用于将String的内码转换为指定的外码的方法。无参数版使用平台的默认编码作为外码,有参数版使用参数指定的编码作为外码;将String的内容用外码编码好,结果放在一个新byte[]返回。
上面的例子里,显然外码是UTF-8,那么调用了String.getBytes()之后得到的byte[]只能表明该外码的性质,而无法碰触到String内码的任何特质。
import java.util.Arrays;
public class Test2 {
public static void main(String[] args) {
char c = '汉';
System.out.println("汉".codePointAt(0)); //汉的码位27721
// char是2个字节 也就是最多能表示 65535个数,unicode 编码超过65535的字符char就无法表示
System.out.println(c);
String s = "汉";
System.out.println(Arrays.toString(s.getBytes()));
// [-26, -79, -119] utf-8编码下 “汉” 需要三个字节表示,但是unicode就是两个字节。
}
}