在看过字节码后,理解这部分的原理就简单多了。
编译期
假设写了这样的代码
public static void main(String[] args) {
String s = "a...a";// 共65534个a
System.out.println(s.length());
String s1 = "a...a";// 共65535个a
System.out.println(s1.length());
}
编译期的时候会生成字节码,所以字符串会被存储在字节码的常量池中,而常量池表示字符串的是通过 CONSTANTUtf8info 描述的
CONSTANT_Utf8_info {
u1 tag;
u2 length;
u1 bytes[length];
}
可以看到 length 的类型为U2,u2代表两个字节,u2是无符号的16位整数,因此理论上允许的的最大长度是2^16=65536。而 java class 文件是使用一种变体UTF-8格式来存放字符的,null 值使用两个 字节来表示,因此只剩下 65536- 2 = 65534个字节
运行期
在 String 类中,是使用一个字符数组来维护字符序列的,其声明如下:
private final char value[];
这也就是说,String 的最大长度取决于字符数组的最大长度,我们知道,在指定数组长度的时候,可以使用 byte、short、char、int 类型,而不能够使用 long 类型。这也就是说,数组的最大长度就是 int 类型的最大值,即 0x7fffffff,十进制就是 2147483647,同理,这也就是 String 所能容纳的最大字符数量。
2^31-1 =2147483647 个 16-bit Unicodecharacter
2147483647 * 16 = 34359738352 位
34359738352 / 8 = 4294967294 (Byte)
4294967294 / 1024 = 4194303.998046875 (KB)
4194303.998046875 / 1024 = 4095.9999980926513671875 (MB)
4095.9999980926513671875 / 1024 = 3.99999999813735485076904296875 (GB)
大约 4个G