1. Unicode和char类型
这里主要是看到Java核心技术3.3.4节产生疑惑,进而探究的过程。在学习的时候参考了部分博客,但是内容都说的不是很详细,因此我自己再更进一步的对其中阐述的不是很清楚的地方进行补充。
目前有的Unicde类型可以使用一个char值描述,另外一些Unicode值则需要两个字符表示,这是因为随着社会的发展,Unicode字符集已经超过了65536个,16位char类型已经无法满足开发需要。因此Java5开始开始通过双Unicode编码的方式解决该问题。
为了解决这个问题,Java采用了两个char类型的字符表示超出字符的unicode编码 ,这两个字符需要联合起来才可以表示,那么Java怎么区分是否需要将这两个字符合并呢?
首先Unicode标准把代码点分成了17个代码平面(Code Plane),编号为#0到#16。每个代码平面包含65,536()个代码点(17*65,536=1,114,112)。
U+000000到U+00FFFF共16位表示“经典”Unicode代码,其余的U+010000到U+10FFFF代表其他。
- 000000 00FFFF “经典”Unicode代码
- 010000 01FFFF 1号辅助字符集
- 020000 02FFFF 2号辅助字符集
- ....
- 0F0000 0FFFFF 15号辅助字符集
- 100000 10FFFF 16号辅助字符集
这些字符集总共需要21位bit来存储这些字符,但是char类型只有16个比特,这就会存在空间不足的问题。
21位来源,首位只有0和1,所以是1位bit,后五位使用16进制表示,每一位需要4个bit,所以总共是21位bit。
为了解决这个问题,Java从经典的Unicode这65536这些代码中拿出2048个,规定他们是Surrogates,让他们两个为一组,来代表编号大于65536的那些字符。编号为 U+D800 至 U+DBFF 的规定为High Surrogates,共1024个。编号为U+DC00 至 U+DFFF 的规定为Low Surrogates,也是1024个。他们组合出现,就又可以多表示1048576中字符,因为高位是10个bit,低位也是10个bit,一共是20个bit。 当Java识别到字符High Surrogates和Low Surrogates之间时,就会将这两个char值一起转换为对应的unicode编码。
10bit指的是=1024
Unicode转UTF-8的方法:
- 如果U<0x10000,U的UTF-16编码就是U对应的16位无符号整数;
- 如果U≥0x10000,我们先计算U'=U-0x10000,然后将U'写成二进制形式:yyyy yyyy yyxx xxxx xxxx;
- U的UTF-16编码(二进制)就是:1101 10yy yyyy yyyy 1101 11xx xxxx xxxx;
高位是1101 10yy的原因解析:这8位二进制表示的范围为:1101 1000-1101 1011分别是D8-DB,符合上边要求的高位编号位于U+D800-U+DBFF;低位是1101 11xx的原因相同。
以U+1F603表示emoj😃为例
U'=U-0x10000=F603写成2进制就是1111 0110 0000 0011,不足20位补0,补位后为0000 1111 0110 0000 0011
接下来将其低位和高位进行拆分,高位是:00 0011 1101,低位是10 0000 0011
对其进行替换可以得到1101 1000 0011 1101 和 1101 1110 0000 0011
对应的Unicode编码为[d838,de03];