关键词: char,UTF-8
考察内容:
熟悉Java char和字符串
了解字符的映射和存储细节
横向对比其他语言
java中的char是用2个字节进行存的,
UTF-8可能是1~3个字节。
例如:
char test = '庆'
是用2 个字节进行存储的。
而它的UTF-U字节是e5ba86,是3个字节。
剖析:
char是什么?UTF-8是什么?占几个字节?和Unicode什么关系?
char里面存的是什么?
System.out.println(Integer.toHexString(test));
打印出来的0x5e,0x86就是Unicode的码点。
Unicode是字符集,ASCII码也是字符集。
字符集完成字符到整数的映射:
(字符) =》 码点
字符集不是编码。
如何存储字符:
字符(人类认知) -> char(字符集) -> byte(计算机存储)
编码:UTF-8
UTF-8与UTF-16的区别:
UTF-8最小的单位是1个字节,UTF-16最小的单位是2个字节。
也就是说,如果这个字符是a,a对应65,它实际上是用ASCII码,也就是7个比特就可以表示。
但是在UTF-16里面也是需要2个字节的。
Java char中存的是UTF-16。
如果把字符换成中文:
类似于“中”字,占1个char就可以了,也就是2个字节。同样是用UTF-16。
如何存储字符:
byte[] bytes= "中".getBytes("utf-16");
System.out.println(bytes.length);
for(byte b : bytes){
System.out.print(Integer.toHexString(Byte.toUnsignedInt(b)));
System.out.print("");
}
结果:
4
fe ff 4e 2d
其中fe ff是字节系列标志。不是代表的真正的内容,而只是让读取这个数据的人知道字节序是什么。
触类旁通:Python2的字符串
# 没问题
byteString = "I'm a byte string."
# 例如utf-8,字面量会用utf-8编码成字节存入字符串
# coding = utf-8
byteString = "中国" # .py文件中存放的是UTF-8编码后的字节。
unicodeString = u"中国" # .py文件中存放的是UCS2(~UTF-16)编码后的字节。
Python是解释执行的,源文件与执行时内存中字符串内容一致。
javac指定编码将字符串统一转为MUTF-8(调用这个命令的时候需要给个encoding的参数)
byte[] byteString= "中".getBytes("utf-8"); 对应于 byteString = "中国"
String unicodeString = "中国" 对应于 unicodeString = u"中国"
unicodeString可以调用encode(),byteString得decode().
让人迷惑的字符串长度:
String emoji= "emoji" //emoji代表QQ表请
System.out.println(emoji.length());
//我们会认为是1,因为看到的是1 ,但不是这样的。
python<=3.2:
String emoji= u"emoji" //emoji代表QQ表请
print(len(emoji))
结果都为2
python>=3.2:
结果等于1.
Java 9并没有改变字符串长度和字符数不一致的情况。
但是对拉丁(Latin)字符的存储空间做了优化。
字符串长度 != 字符数
题目结论:
java char不存UTF-8的字节,而是UTF-16的.
Unicode通用字符集占2个字节,例如“中”.
Unicode是扩展字符集需要用一对char来表示,例如“emoji”
Unicode是字符集,不是编码,作用类似于ASCII码。
Java String的length不是字符数。