字符串';Java中的最大长度-调用length()方法

字符串';Java中的最大长度-调用length()方法,java,string,Java,String,在Java中,引用length()方法调用时,字符串对象的最大大小是多少 我知道length()将字符串的大小返回为char[] 由于数组必须用整数索引,因此数组的最大长度为Integer.MAX_INT(231-1或2147483647)。当然,这是假设您有足够的内存来容纳该大小的数组。考虑到类的方法返回一个int,该方法将返回的最大长度为,即2^31-1(约20亿) 就数组的长度和索引而言,(例如char[],这可能是Strings实现内部数据表示的方式),如下所示: 数组中包含的变量 没有

Java中,引用
length()
方法调用时,
字符串
对象的最大大小是多少


我知道
length()
字符串的大小返回为
char[]

由于数组必须用整数索引,因此数组的最大长度为
Integer.MAX_INT
(231-1或2147483647)。当然,这是假设您有足够的内存来容纳该大小的数组。

考虑到类的方法返回一个
int
,该方法将返回的最大长度为,即
2^31-1
(约20亿)

就数组的长度和索引而言,(例如
char[]
,这可能是
String
s实现内部数据表示的方式),如下所示:

数组中包含的变量 没有名字;相反,他们是 由数组访问表达式引用 使用非负整数索引的 价值观这些变量称为 阵列的组件。如果一个数组 有
n
组件,我们说
n
是 阵列的长度;组成部分 使用整数引用数组 从
0
n-1
的索引,包括在内

此外,索引必须通过
int
值进行,如中所述:

数组必须按
int
值进行索引

因此,似乎极限确实是
2^31-1
,因为这是非负
int
值的最大值


但是,可能还有其他限制,例如数组的最大可分配大小。

显然它绑定到一个int,即0x7FFFFFFF(2147483647)。这得出结论,当与
DataInput
DataOutput
一起使用时,字符串的长度受到字符串的修改UTF-8表示的字节数的限制

此外,Java虚拟机规范中定义了如下结构

CONSTANT_Utf8_info {
    u1 tag;
    u2 length;
    u1 bytes[length];
}
您可以发现“length”的大小为两个字节

特定方法(例如
String.length()
)的返回类型为
int
并不总是意味着其允许的最大值为
Integer.MAX\u值。相反,在大多数情况下,选择
int
只是出于性能原因。Java语言规范指出,小于
int
的整数在计算之前会转换为
int
(如果我的内存没有问题的话),这是在没有特殊原因的情况下选择
int
的一个原因

编译时的最大长度最多为65536。请再次注意,长度是表示的字节数,而不是
字符串中的字符数


String
对象在运行时可能有更多的字符。但是,如果要将
String
对象与
DataInput
DataOutput
接口一起使用,最好避免使用太长的
String
对象。当我实现与
DataInput.readUTF()
DataOutput.writeUTF(String)
等价的Objective-C时,我发现了这个限制。String类的length()方法的返回类型是int

公共整数长度()

提及

因此int的最大值是2147483647

字符串在内部被视为字符数组,因此索引是在最大范围内完成的。 这意味着我们无法索引2147483648成员。因此,java中字符串的最大长度为2147483647

在java中,基元数据类型int为4字节(32位)。由于1位(MSB)用作符号位,因此范围限制在-2^31到2^31-1(-2147483648到2147483647)之间。
我们不能使用负值进行索引。因此,我们可以使用的范围显然是从0到2147483647。

我有一个2010 iMac,内存为8GB,运行Eclipse Neon.2发行版(4.6.2)和Java 1.8.025。使用VM参数-Xmx6g,我运行了以下代码:

StringBuilder sb = new StringBuilder();
for (int i = 0; i < Integer.MAX_VALUE; i++) {
    try {
        sb.append('a');
    } catch (Throwable e) {
        System.out.println(i);
        break;
    }
}
System.out.println(sb.toString().length());
因此,似乎最大数组大小为~1207959549。然后我意识到,我们实际上并不关心Java是否耗尽了内存:我们只是寻找最大数组大小(它似乎是某个地方定义的常量)。因此:

所以,看起来max是整数。max_值是-2,或者(2^31)-3

另外,我不知道为什么我的
StringBuilder
1207959550
处最大,而我的
char[]
在(2^31)-3处最大。似乎
AbstractStringBuilder
将其内部
char[]
的大小增加了一倍,这样可能会导致问题。

如中所述,java以JVM规范的形式表示Unicode字符串,2个字节分配给长度(而不是字符串的字符数)。
为了扩展答案,库的包含以下内容:

public ByteVector putUTF8(最终字符串字符串值){
int charLength=stringValue.length();
如果(字符长度>65535){
//如果字符数>65535,而不是UTF-8编码长度,则无法容纳2个字节。
抛出新的IllegalArgumentException(“UTF8字符串太大”);
}
对于(int i=0;i='\u0001'&&charValue 1byte,则调用
encodeUTF8
方法:

final ByteVector encodeUtf8(final String stringValue,final int offset,final int maxByteLength/*=65535*/){
int charLength=stringValue.length();
int byteLength=偏移量;
for(int i=偏移量;iRequested array size exceeds VM limit
1207959550
for (int i = 0; i < 1_000; i++) {
    try {
        char[] array = new char[Integer.MAX_VALUE - i];
        Arrays.fill(array, 'a');
        String string = new String(array);
        System.out.println(string.length());
    } catch (Throwable e) {
        System.out.println(e.getMessage());
        System.out.println("Last: " + (Integer.MAX_VALUE - i));
        System.out.println("Last: " + i);
    }
}
Requested array size exceeds VM limit
Last: 2147483647
Last: 0
Requested array size exceeds VM limit
Last: 2147483646
Last: 1
Java heap space
Last: 2147483645
Last: 2