String字符串的最⼤长度是多少?
在学习和开发过程中,我们经常会讨论 short ,int 和 long 这些基本数据类型的取值范围,但是对于 String 类型我们好像很少注意它的“取值范围”。那么对于String 类型,它到底有没有长度限制呢?
其实 String 类型的对象,他们是有长度限制的, String 对象并不能“存储”⽆限长度的字符串。关于 String 的长度限制要从编译时限制和运⾏时限制两⽅⾯考虑。
编译期限制
有JVM虚拟机相关知识的同学肯定知道,下⾯定义的字符串常量“⾃由之路”会被放⼊⽅法区的常量池中。
String s = "⾃由之路";
System.out.println(s);
Stirng 长度之所以会受限制,是因JVM规范对常量池有所限制。常量池中的每⼀种数据项都有⾃⼰的类型。Java中的UTF-8编码的Unicode字符串在常量池中以CONSTANT_Utf8类型表⽰。
CONSTANT_Utf8的数据结构如下:
CONSTANT_Utf8_info {
u1 tag;
unicode字符的种类有u2 length;
u1 bytes[length];
}
我们重点关注下长度为 length 的那个bytes数组,这个数组就是真正存储常量数据的地⽅,⽽ length 就是数组可以存储的最⼤字节数。length 的类型是u2,u2是⽆符号的16位整数,因此理论上允许的的最⼤长度是2^16-1=65535。所以上⾯byte数组的最⼤长度可以是65535。
//65535个d,编译报错
String s = "dd..dd";
//65534个d,编译通过
String s1 = "dd..d";
上⾯的列⼦中长度为65535的字符串s还是编译失败了,但是长度为65534的字符串 s1 编译是成功的。这个好像和我们刚刚的结论不符合。
其实,这是Javac编译器的额外限制。在Javac的源代码中可以到以下代码:
private void checkStringConstant(DiagnosticPosition var1, Object var2) {
if (s == 0 && var2 != null && var2 instanceof String && ((String)var2).length() >= 65535) {
(var1, "limit.string", new Object[0]);
++s;
}
}
代码中可以看出,当参数类型为String,并且长度⼤于等于65535的时候,就会导致编译失败。
这⾥需要重点强调下的是:String 的限制还有⼀个部分,那就是对字符串底层存储的字节数的限制。也就是说:在编译时,⼀个字符串的长度⼤于等于65535或者底层存储占⽤的字节数⼤于65535时就会报
错。这句话可能⽐较抽象,下⾯举个列⼦就清楚了。
Java中的字符常量都是使⽤UTF8编码的,UTF8编码使⽤1~4个字节来表⽰具体的Unicode字符。所以有的字符占⽤⼀个字节,⽽我们平时所⽤的⼤部分中⽂都需要3个字节来存储。
//65534个字母,编译通过
String s1 = "dd..d";
//21845个中⽂”⾃“,编译通过
String s2 = "⾃⾃...⾃";
//⼀个英⽂字母d加上21845个中⽂”⾃“,编译失败
String s3 = "d⾃⾃...⾃";
对于s1,⼀个字母d的UTF8编码占⽤⼀个字节,65534字母占⽤65534个字节,长度是65534,长度和存储都没超过限制,所以可以编译通过。
对于s2,⼀个中⽂占⽤3个字节,21845个正好占⽤65535个字节,⽽且字符串长度是21845,长度和存
储也都没超过限制,所以可以编译通过。
对于s3,⼀个英⽂字母d加上21845个中⽂”⾃“占⽤65536个字节,超过了存储最⼤限制,编译失败。
运⾏时限制
String 运⾏时的限制主要体现在 String 的构造函数上。下⾯是 String 的⼀个构造函数:
public String(char value[], int offset, int count) {
...
}
上⾯的count值就是字符串的最⼤长度。在Java中,int的最⼤长度是2^31-1。所以在运⾏时,String 的最⼤长度是2^31-1。
但是这个也是理论上的长度,实际的长度还要看你JVM的内存。我们来看下,最⼤的字符串会占⽤多⼤的内存。
(2^31-1)*2*16/8/1024/1024/1024 = 4GB
所以在最坏的情况下,⼀个最⼤的字符串要占⽤4GB的内存。如果你的虚拟机不能分配这么多内存的话,会直接报错的。
JDK9以后对String的存储进⾏了优化。底层不再使⽤char数组存储字符串,⽽是使⽤byte数组。对于LATIN1字符的字符串可以节省⼀倍的内存空间。
简单总结
String 的长度是有限制的。
编译期的限制:字符串的UTF8编码值的字节数不能超过65535,字符串的长度不能超过65534;
运⾏时限制:字符串的长度不能超过2^31-1,占⽤的内存数不能超过虚拟机能够提供的最⼤值。
推荐
欢迎⼤家关注我的「程序员⾃由之路」
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论