String的Java中的最大长度 - 调用length()方法

时间:2009-05-03 02:31:36

标签: java string

Java 中,String对象可能具有的最大大小是什么,参考length()方法调用?

我知道length()会将String的大小恢复为char [];

7 个答案:

答案 0 :(得分:152)

考虑到String类'length方法返回int,方法返回的最大长度为Integer.MAX_VALUE,即2^31 - 1 (或大约20亿。)

就数组的长度和索引而言(例如char[],这可能是String s)内部数据表示的实现方式,Chapter 10: Arrays The Java Language Specification, Java SE 7 Edition说出以下内容:

  

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

此外,索引必须为int值,如Section 10.4中所述:

  

数组必须按int值编制索引;

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

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

答案 1 :(得分:20)

java.io.DataInput.readUTF()java.io.DataOutput.writeUTF(String)表示String对象由 两个字节 的长度信息和{{3}表示字符串中每个字符的表示。结论是,与DataInputDataOutput一起使用时,字符串的长度受字符串的修改后的UTF-8表示的字节数限制。

此外,Java虚拟机规范中的modified UTF-8定义了如下结构。

CONSTANT_Utf8_info {
    u1 tag;
    u2 length;
    u1 bytes[length];
}

您可以发现'length'的大小为两个字节

某种方法的返回类型(例如String.length())为int并不总是意味着其允许的最大值为Integer.MAX_VALUE。相反,在大多数情况下,仅出于性能原因选择int。 Java语言规范说大小小于int的整数在计算之前被转换为int(如果我的记忆正确地为我服务),这是选择int的一个原因没有什么特别的原因。

编译时的最大长度最多为65536.再次注意,长度是The specification of CONSTANT_Utf8_info表示的字节数,而不是String对象中的字符数。

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

答案 2 :(得分:18)

由于数组必须用整数索引,因此数组的最大长度为Integer.MAX_INT(2 31 -1或2 147 483 647)。假设你有足够的内存来容纳那个大小的数组。

答案 3 :(得分:5)

显然它绑定到一个int,即0x7FFFFFFF(2147483647)。

答案 4 :(得分:4)

我有一个带有8GB RAM的2010 iMac,运行带有Java 1.8.0_25的Eclipse Neon.2 Release(4.6.2)。使用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());

打印:

Requested array size exceeds VM limit
1207959550

因此,似乎最大数组大小约为1,207,959,549。然后我意识到我们实际上并不关心Java是否内存不足:我们只是在寻找最大的数组大小(这似乎是在某处定义的常量)。所以:

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

所以,似乎最大值是Integer.MAX_VALUE - 2,或者(2 ^ 31) - 3

P.S。我不确定为什么StringBuilder 1207959550在我char[]最大值(2 ^ 31)-3时达到最大值AbstractStringBuilder。似乎char[]将其内部func foo(param1: Int, param2: Double) -> (retA: String, retB: [Int]) { // ... } 的大小增加一倍以增加它,因此可能会导致问题。

答案 5 :(得分:3)

String类的length()方法的返回类型是 int

  

public int length()

参考http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#length()

因此int的最大值为 2147483647

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

原始数据类型int在java中是4个字节(32位)。由于1位(MSB)用作符号位,范围被约束在 -2 ^ 31到2 ^ 31-1 ( - 2147483648至2147483647)。 我们不能使用负值进行索引。所以我们可以使用的范围显然是0到2147483647.

答案 6 :(得分:0)

Takahiko Kawasaki's answer中所述,java以modified UTF-8的形式表示Unicode字符串,在JVM-Spec CONSTANT_UTF8_info Structure中,长度分配了2个字节(而不是字符数)的字符串)。
为了扩展答案,ASM jvm bytecode库的putUTF8 method包含以下内容:

public ByteVector putUTF8(final String stringValue) {
    int charLength = stringValue.length();
    if (charLength > 65535) {   
   // If no. of characters> 65535, than however UTF-8 encoded length, wont fit in 2 bytes.
      throw new IllegalArgumentException("UTF8 string too large");
    }
    for (int i = 0; i < charLength; ++i) {
      char charValue = stringValue.charAt(i);
      if (charValue >= '\u0001' && charValue <= '\u007F') {
        // Unicode code-point encoding in utf-8 fits in 1 byte.
        currentData[currentLength++] = (byte) charValue;
      } else {
        // doesnt fit in 1 byte.
        length = currentLength;
        return encodeUtf8(stringValue, i, 65535);
      }
    }
    ...
}

但是,当代码点映射> 1byte时,它将调用encodeUTF8方法:

final ByteVector encodeUtf8(final String stringValue, final int offset, final int maxByteLength /*= 65535 */) {
    int charLength = stringValue.length();
    int byteLength = offset;
    for (int i = offset; i < charLength; ++i) {
      char charValue = stringValue.charAt(i);
      if (charValue >= 0x0001 && charValue <= 0x007F) {
        byteLength++;
      } else if (charValue <= 0x07FF) {
        byteLength += 2;
      } else {
        byteLength += 3;
      }
    }
   ...
}

从这个意义上说,最大字符串长度为65535字节,即utf-8编码长度。而不是char
您可以从上面的utf8结构链接中找到JVM的修改后的Unicode代码点范围。