字符串还有长度限制?是的没错。
先看简单的情况。
// 并不是显示的在类中new,请看后面注意
String str = new String("str");
如果通过new的方法来创建String,可以通过String的另一个构造方法得出,长度的限制是Integer.MAX_VALUE
public String(char value[], int offset, int count)
给出偏移位置,与截取长度,通过char数组创建字符串。
开始正文
更常用的创建字符串的方式一般是这样的。
String str = "str";
本文的重点,也就是讲述这种创建方式长度限制。
java类文件结构
根据Java虚拟机规范:Class文件格式采用一种类似C语言结构体的为伪结构存储数据,这种伪结构中只有两种数据类型:无符号数和表,后面的解析都要以这两种数据结构为基础。
无符号数属于基本数据类型,以u1,u2,u4,u8来分别代表1个字节,2个字节,4个字节和8个字节的无符号数,无符号数可以用来描述数字,索引引用、数量值、或者按照UTF-8编码构成的字符串。
表是有多个无符号数或者其他表作为数据项结构的符合数据结构。
(摘自深入理解java虚拟机)
常量池
如果直接通过双引号的方式创建字符串,编译的时候会给常量池里放一份,常量池中有14种记录常量的数据结构,有一种用来记录字符串 CONSTANT_Utf8_info。字符串长度受CONSTANT_Utf8_info类型的限制。
CONSTANT_Utf8_info结构
类型 | 名称 | 数量 |
---|---|---|
u1 | tag | 1 |
u2 | length | 1 |
u1 | bytes | length |
tag 用来表示常量池数据类型,u2,用来表示UTF-8编码表示的字符串长度。后面紧接着就是 length长度连续数据表示具体的字符串。
结论
u2 类型占两个字节,表示长度限制为 65536。 而实际上,字符串的长度限制为65534个而java class 文件是使用一种变体UTF-8格式来存放字符的,null值使用两个字节来表示,因此只剩下 65536- 2 = 65534个字节。
注意
// 65535个a,显示的在类中创建,""中的内容也会放到常量值
String str = new String("aaa...aaa");
运行期间,创建的字符串长度不受限制。
public static void main(String[] args) {
String str = "";
for (int i = 0; i < 65535; i++) {
str += "aa";
}
String name = new String(str);
System.out.println(name.length());
}