在Java中的string的最大长度 – 调用length()方法
我的问题是非常基本的,但是我没有在Googlesearch上find答案。
在Java中 ,指向length()
方法调用的String
对象可能具有的最大大小是多less?
我知道length()
返回一个String
的大小为char []
;
考虑到String
类的length
方法返回一个int
,那么该方法返回的最大长度将是Integer.MAX_VALUE
,即2^31 - 1
(或大约20亿)。
就数组的长度和索引而言(比如char[]
,这可能是为String
实现内部数据表示的方式), 第10章: Java SE 7中的 数组说明如下:
包含在数组中的variables没有名字; 相反,它们是由使用非负整数索引值的数组访问expression式引用的。 这些variables被称为数组的组件 。 如果一个数组有
n
分量,我们说n
是数组的长度 ; 数组的元素使用从0
到n - 1
整数索引进行引用。
而且,索引必须是int
值,如10.4节所述 :
数组必须用
int
值进行索引;
因此,看起来这个极限确实是2^31 - 1
,因为这是一个非负的int
值的最大值。
但是,可能会有其他限制,例如数组的最大可分配大小。
由于数组必须使用整数进行索引,因此数组的最大长度为Integer.MAX_INT
(2 31 -1或2 147 483 647)。 这是假设你有足够的内存来保存这个大小的数组,当然。
java.io.DataInput.readUTF()
和java.io.DataOutput.writeUTF(String)
声明一个String
对象由两个字节的长度信息和string中每个字符的修改的UTF-8表示forms表示。 由此得出结论,当与DataInput
和DataOutput
一起使用时,String的长度受string修改的UTF-8表示字节数的限制。
另外,Java虚拟机规范中的CONSTANT_Utf8_info
规范定义了如下结构。
CONSTANT_Utf8_info { u1 tag; u2 length; u1 bytes[length]; }
你可以发现'长度'的大小是两个字节 。
某个方法(例如String.length()
)的返回types是int
并不总是意味着它允许的最大值是Integer.MAX_VALUE
。 相反,在大多数情况下, int
只是出于性能原因而select的。 Java语言规范说,在计算之前(如果我的内存正确地为我服务),那些小于int
被转换为int
,并且这是在没有特殊原因时selectint
一个原因。
编译时的最大长度至多为65536.再次注意,长度是修改的UTF-8表示的字节数,而不是String
对象中的字符数。
String
对象在运行时可能有更多的字符。 但是,如果要使用带有DataInput
和DataOutput
接口的String
对象,最好避免使用太长的String
对象。 当我实现了DataInput.readUTF()
和DataOutput.writeUTF(String)
Objective-C等价物时,我发现了这个限制。
显然它绑定到一个int,它是0x7FFFFFFF(2147483647)。
String类的length()方法的返回types是int 。
public int length()
请参阅http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#length();
所以int的最大值是2147483647 。
string在内部被视为char数组,因此索引是在最大范围内完成的。 这意味着我们不能索引第2147483648个成员。所以在java中String的最大长度是2147483647。
原始数据typesint在java.As中为4个字节(32位)。1位(MSB)用作符号位 。范围限制在-2 ^ 31到2 ^ 31-1 (-2147483648到2147483647)之间。 我们不能使用负值进行索引。显然,我们可以使用的范围是从0到2147483647。
我有一台带有8GB内存的2010 iMac,使用Java 1.8.0_25运行Eclipse Neon.2版本(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
所以,最大arrays大小似乎是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
PS我不知道为什么我的StringBuilder
超出了1207959550
而我的char[]
超出(2 ^ 31)-3。 AbstractStringBuilder
似乎将内部char[]
的大小扩大了两倍,所以可能会导致问题。