Java 的外码

外码(exteranl encoding):即程序与外部交互时用的字符编码,比如序列化用的字符编码
关于Java外码,String默认序列化使用utf-8。 值得一提的是,Java编译后的class文件中字符串常量、和符号名字也使用utf-8编码。另外当然对外输出也可指定编码。

Java的内码

  • 内码(internal encoding) 即程序程序内部使用的字符编码,例如char或String在内存中的编码。
    java应用程序在运行时,内存中的char、String使用utf-16编码,所以Java中一个char 2个字节。总所周知,java也是使用unicode字符集,那utf-16和unicode是什么关系呢?

1. Unicode和Utf16区别

  1. unicode是字符集, 它的码位的范围是:U+0000 to U+10FFFF
  2. utf-x(指utf-8\16\32)则是一种针对unicode字符集的编码方式。 记住unicode是字符集,而utf-x是具体的编码方式。

这里有个问题,unicode字符集码位范围: U+0000 ~ U+10FFFF。而java内码使用utf-16编码,用2个字节表示一个字符,最多可表示范围是0~2^16 即U+0000 ~ U+FFFF, 这个范围远不够表示unicode所有字符,怎么办?

下面引用stackoverFlow一个回答

Early Java versions represented Unicode characters using the 16-bit char data type. This design made sense at the time, because all Unicode characters had values less than 65,535 (0xFFFF) and could be represented in 16 bits. Later, however, Unicode increased the maximum value to 1,114,111 (0x10FFFF). Because 16-bit values were too small to represent all of the Unicode characters in Unicode version 3.1, 32-bit values — called code points — were adopted for the UTF-32 encoding scheme. But 16-bit values are preferred over 32-bit values for efficient memory use, so Unicode introduced a new design to allow for the continued use of 16-bit values. This design, adopted in the UTF-16 encoding scheme, assigns 1,024 values to 16-bit high surrogates(in the range U+D800 to U+DBFF) and another 1,024 values to 16-bit low surrogates(in the range U+DC00 to U+DFFF). It uses a high surrogate followed by a low surrogate — a surrogate pair — to represent (the product of 1,024 and 1,024)1,048,576 (0x100000) values between 65,536 (0x10000) and 1,114,111 (0x10FFFF)

翻译一下就是

早期,Java用16位char来表示Unicode字符,这个设计在当时是正确的,因为当时unicode的value值都小于65,535 (即0xFFFF),用16位足够表示了.
然而后面unicode扩展到最大值为 1,114,111 (0x10FFFF)。这时16位就显得太小了。此时,更年轻的UTF-32已采用32位来表示一个字符。 但是16位相比32位更节省内存,为了方便继续使用16位来表示,所以Unicode引入了一个设计:
在utf-16的编码规则基础上,分配了1024个值来作为high surrogates范围(U+D800到U+DBFF),
此外再分配了1024个值作为low surrogates(U+DC00到U+DFFF),然后用 high surrogates 和 low surrogates组成一对(组合数为1024*1024= 2^20次方,用来表示0x10000至0x10FFFF的值。

也即是说,16位太小,不够表示0x10000至0x10FFFF的值(一共2^20),只够表示U+0000 to U+FFFF(0~2^10)
那怎么办呢?unicode就想,用两个16bit组成一对来表示,16位数值范围内分配210个作为高位替代码,210个低位替代码,两个结合起来就是220, 刚好表示0x10000至0x10FFFF的值

相关概念

  • 码位(code point): 指字符集里的字符的编号
  • 编码单位(code unit): 编码一个‘码位’最少的字节数,比如utf8最少一个字节、 utf-16的最少2个字节