Java中字符串的最大长度肯定不会是无穷大,这个毫无疑问,受限于物理机器内存,分配的Java虚拟机内存。归根结底跟该字符串存储的位置,表达方式有关。如果该字符串是在Java源文件中定义的,其长度超过了65534,那么编译会报错,如果是通过程序动态生成的,那么其大小肯定是可以超过65534的。产生这种差别的原因是,编译源文件后生成的是class文件,字符串存储在Class文件的常量池中,类型为Constant_utf8_info,数据结构为一个1字节代表数据类型,一个2字节的无符号数表示后续的字节长度,再跟着的就是该U2长度的字节数组。很容易推出这个字节数组的长度不能超过2^16=65536。
下面是验证的过程:
1,编写如下Java文件:
public class Hello {
public static void main(String[] args){
// 65534个字符a
String maxLength="aaaaaaaaaa...";
System.out.println(maxLength.length());
}
}
一直添加a的个数,当为65534时是可以正常编译的,为65535时则会报出这个错误:
保持65534个a编译,执行程序,输出如下:
2,用hex打开class文件,查看16进制格式,标出的位置表示的是65534个a在常量池中的位置:
3,修改FE为FF,然后再插入一个16进制为61的字节,即字符a,红色代表发生了修改,如下:
4,保存后在重新执行程序,输出值为65535,如下:
以上过程说明,实际上在Class文件中,确实是可以支持最大65535个字符,即2字节无符号数的最大值,但是源文件中却会比最大值少一个,我猜测也许是从源文件编译成字节码的过程中,可能有类似于;的结束符占用了一个字符的位置。(应该可以从javac的源码中找到答案,等找到后再补充)。
备注:
上面说的是从源文件生成的问题,如果是程序运行时动态生成的话,理论值应该是2^32或者2^64(未验证)。因为这个时候的字符串应该是(不是绝对的)存在Java堆中,在本地方法只存储该对象的引用,即reference类型,该类型可能是4个字节,也可能是8个字节。所以理论值是2^32或者2^64