1. char
“java 中有个基本类型 char
, 它占用固定的 2 byte
空间来表示字符, 又因为 java 设计之初就采用了 Unicode
编码,所以 char
能表示所有字符包括中文.”
但 2 字节最多只能标识 65536 个字符, 它是怎么能囊括那么多字符的呢? 仅所有汉字就不止 6 万.
java 中的 char
确实使用 2 byte
空间, 它实际使用的是 UCS-2
也就是 plane 0
, 只能表述 65536
个字符, 对于超出其范围的其它 plane
内容, 请看下图:
一旦你使用了大于 UCS-2
的字符, 那么编译器会直接报错.
其实也就是说 char
使用的是 UTF-16
格式. 有个建议是尽量别用 char
类型, 因为它会导致一些隐蔽的错误. 比如, 当你在用 String
时你定义了一个 虫
, 你想当然的认为一个 char
就能盛放String
中的一个字符 (毕竟 char
是字符, 而 String
就是描述的 char
数组), 但是你会发现其实这个 String
的 length()
是 2 而不是 1, 因为它超出了 UCS-2
, String
用两个char
的位置 (4 字节) 来表示了这个 char
, 而 String
本该用一个 char
的位置来表示它才对.
2. String
首先, String
能够支持的字符与你写代码时选择的编码方式有关, 当你选择 UTF
编码时, 你可以随便使用 Unicode
字符, 用没脚 虫
当变量名都随你. 使用 GBk
时, 没脚虫 虫
不被支持 (GBK
收录的少一些或者这是日本字)
其次, String
在 Java 中是被定义为 char
数组来组织的, 所以你定义的 String
最终要被转换成char
来存放, 但是, 不要认为超出 char
的 65536 就不能存了, 如果超出了它会用 2 个 char
来存放.
在这里有两种方向来说 1 个 String
占用的空间:
2.1. 在 Java 中实际使用的空间
这与使用的编码有关:
UTF-8 : 2 或 4 byte
, 其实就是 1 个 char
或者 2 个 char
;
GBk : 2 byte
, 就是 1 个 char
.
2.2 如果对其编码,所需要的空间(String.getBytes())
UTF-8 : 1~4 byte
, ASCII
用 1 byte
, 汉字大部分用 3 byte
, 其它字符参照上边 UTF2.2
的算法, 超出 UCS-2
的部分比如那个 虫
就会是 4 byte
.
GBk : ASCII
使用 1 byte
, 其它中文 2 byte
.
3. 额外的部分—-从 java 到 class 文件
无论 .java
文件你用 GBK
或者 UTF-8
来编码, 编译器在将其编译为 .class
文件后, 如果其中有字符串, 会使用 UTF-8
来编码存储字节, 占用 1~4 byte
. 详细来说, 就是在 .class
文件的常量池部分, 这种字符串数据使用的数据结构是 CONSTANT_Utf8_info
, 代表 UTF-8
编码的字符串.