String 是我们非常常用的一个类,尤其是 length()方法。而要清晰地理解 length,首先需要对字符编码有一定了解。众所周知,计算机只能识别高低电平——也就是 0,1。0,1 显然是无法表示现实中的字符的,所以后来,人们定义一个电平作为 1-bit,以不同 bit 的排列组合来代表不同的字符。于是,一个采用 8-bit、也就是 1-byte 来的表示字符的字符集:ASCII 字符集诞生了。
8bit 的排列组合,最多可以有 2^8=256 种形式,也就是说 ASCII 字符集至多可以表示 256 种字符。这对英文字母来说绰绰有余,但在世界范围内,这个表示范围显然是远远不够的。于是,为了能表示所有文字,Unicode 字符集应运而生。
最初,Unicode 字符集被设计成 2-byte,可以表示 2^16=65536 个字符。而后随着内容的增加,这 6 万多个字符也不够用了。于是,unicode 规范将这 65536 个字符合集便被作为基本多文种平面(Basic Multilingual Plane,BMP),并添加了同样要求以 2-byte 实现的辅助平面(Supplementary Planes)。这样,BMP 与 SP 相结合,unicode 字符集可以表示 2^32 次方个字符。
4-byte 的虽然暂时解决了表示字符数量问题,但实际使用中,绝大多数的字符还是可以用 1-byte 或者 2-byte 表示。如果一律以 4-byte 处理,无疑会造成巨大的空间浪费。于是,可以经过某种转换实现 unicode 字符集的编码规范出现了,常见的有 utf-8/utf-16 等。
我们将一个 unicode 字符编码称为 1-code point。在 java 中,.class 采用 utf-8,JVM 采用 utf-16。utf-8 是变长编码,而 utf-16 固定用 2byte 或 4byte 进行存储。在 utf-16 中,2-byte 称为 1-code unit,而 1-code point,或用 1-code unit 表示,或用 2-code unit 表示。
string.length()返回的长度,实际上是 code unit 数量:
1 |
|
char 的包装类 Character 实现了遵循 utf-16 的各种方法,而在 String 类中,以 char[] value 表示 string 的值,并调用 Character 中各种方法,如进行 code point 判断、大小写转换等。
1 | public final class String |