面试题二:Java String可以有多长?

Java String可以有多长?

一、面试官视角:这道题想考察什么?

  • 是否对字符串编解码有深入了解
  • 是否对字符串在内存当中的存储形式有深入了解
  • 是否对Java虚拟机字节码有足够的了解
  • 是否对Java虚拟机指令有一定的认识

二、题目剖析:

1、字符串有多长是指字符数还是字节数?

2、字符串有几种存在形式?

3、字符串的不同形式受到何种限制?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
String longString = "aaa ... aaa"; // 存储在栈里,开辟空间小
// 长度 <= 65535,字符串在字节码(*.class)里,是UTF-8的结构存储的
// Latin字符编译成字节码,是以MUTF-8(Modified UTF-8)编码的形式存储到字节码(*.class)中
// 在Java编译器:当字符串长度达到65535时,会报错,这是因为在源码(Gen.java)中,((String)constValue).length() < Pool.Max_STRING_LENGTH,而不是 <= 或 >
// 在Kotlin编译器中:当字符串长度达到65535时,不会报错,因为在源码中,是 >
// 总结:(存在栈上面的String)
// 1、受字节码限制,字符串最终的MUTF-8字节数不超过65535
// 2、Latin字符,受Javac代码限制,最多65534个
// 3、非Latin字符最终对应字节个数差异较大,最多字节个数是65535
// 4、如果运行时方法区设置较小,也会受到方法区大小的限制

byte[] bytes = loadFromFile(new File("superLongText.txt"));
String superLongString = new String(bytes); //存储在堆里,开辟空间大
// new String后背是char value[]数组,这个数组受到虚拟机指令(newarrary[int])的限制,而newarrary[int]数组理论最大个数为Integer.MAX_VALUE
// 真的就是Integer.MAX_VALUE,这么大吗?不一定,因为ArrayList.java源码中的常量:MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8,也就是说实际上会小于Integer.MAX_VALUE

// 总结:(存在堆上面的String)
// 1、受虚拟机指令限制,字符数理论上限为Integer.MAX_VALUE
// 2、受虚拟机实现限制,实际上限可能会小于Integer.MAX_VALUE
// 3、如果堆内存较小,也会受到堆内存的限制

三、题目结论:

  • Java String字面量形式
    • 字节码中CONSTANT_Utf8_info的限制
    • Javac源码逻辑的限制
    • 方法区大小的限制
  • Java String运行时创建在堆上的形式
    • Java虚拟机指令newarray的限制
    • Java虚拟机堆内存大小的限制