1、String类型最大能存多少字符
1.1、从String.class的定义来看
内部是用char[]数组实现的,char[]数组的长度用int定义,Integer.MAX_VALUE ,约为2G
1.1、运行时限制:String当临时变量使用时
在普通的代码调临时创建的String变量,存在java的堆中,String的长度理论上取决于传入的byte[]长度。
参考ArrayList数组分配置长度可知,有些虚拟机在数组中保留一些头词,数组的长度不能超过
Integer.MAX_VALUE - 8
尝试分配更大的数组可能会导致OOM,
即byte[]的最大长度不能超过
byte[] bytes = new byte[Integer.MAX_VALUE-8];
当然,当JVM的堆空间不足以分配时,也会抛出OOM异常。
1.2、编译期的限制:String变量是一个类中的全局变量时
private final static String LONG_STRING = "aaa";
这样定义的字符串在编译期就已经确定了,"aaa"字符串存放在方法区的常量池中,
代码编译成字节码以后,String的数据结构为CONSTANT_Utf8_info表示,即
CONSTANT_Utf8_info{
u1 tag;
u2 length; // 0~65535
u1 bytes[length];
}
u2 length,表示byte数组的长度,u2无符号,表示2个字节16位,能表示的最大值为2^16-1=65535
因此,最多只能存放65535个字节长度的字符串
由Javac编译器的额外限制。在Javac的源代码中可以找到以下代码:
private void checkStringConstant(DiagnosticPosition var1, Object var2) {
if (this.nerrs == 0 && var2 != null
&& var2 instanceof String
&& ((String)var2).length() >= 65535) {//对string长度的限制
this.log.error(var1, "limit.string", new Object[0]);
++this.nerrs;
}
}
代码中可以看出,当参数类型为String时,并且长度大于等于65535的时候,就会导致编译失败。
即String的字符长度(字符个数)要小于65535,字节数不能超过65535。
因此:
当字符串是一个字符占用一个字节时,如全英文时,一个字符占一个字节,可以存65534个字符。
当字符串是一个字符占用多个字节时,如全中文时,如果是utf-8编码,一个中文占3个字节,那和可存65533/3=21845个字符串。
结论:
编译期的限制:字符串的UTF8编码值的字节数不能超过65535,字符串的长度不能超过65534;
运行时限制:字符串的长度不能超过2^31-1,占用的内存数不能超过虚拟机能够提供的最大值。