2016-05-17 68 views
2

我试图从文件中直接反序列化字符串,并且对于很长的字符串有一个问题:Java字符串的字符数限制等于Integer.MAX_VALUE,即31^2-1。Java String UTF-8限制

但是我的问题是:当我有一个小于这个大小的UTF-8字符串,但是由大小超过1个字节的字符组成时会发生什么,然后我要求Java给我字节数组?

为了让它更清楚,如果我可以运行此代码会发生什么? (我没有足够的RAM):

String toPrint = ""; 
String string100 = ""; 
int max = Integer.MAX_VALUE -100; 
for (int i = 0; i < 100; i += 10) { 
    string100 += "1234567ñ90"; 
} 
for (int i = 0; i < max; i += 100) { 
    toPrint += string100; 
} 
System.out.println("String complete!"); 
byte[] byteArray = toPrint.getBytes(StandardCharsets.UTF_8); 
System.out.println(byteArray.length); 
System.exit(0); 

它打印“字符串完成!”吗?或者它之前破裂了?

回答

3

从根本上说,上Strings的限制是它们的内部的char阵列不能超过的最大数组长度,其大致Integer.MAX_VALUE和比你的可变max更大更长。字符串以UTF-16存储它们的字符,因此字符串的UTF-16表示不能超过最大数组长度。 UTF-8中的字节数和逻辑字符数(Unicode代码点或UTF-32字符)最终并不重要。

现在我们来看看您的具体示例。由于“1234567-90”中的10个字符均为单个UTF-16值,因此该字符串占用了Stringchar阵列的10个值。尽管你的代码性能糟糕,内存要求高,但它最终应该是“字符串完整”!如果有足够的可用内存。但是,转换为UTF-8时会中断,因为字符串的UTF-8表示长于最大数组长度,因为“ñ”需要多个字节。

+0

我同意可怕的表现,它只是一个概念验证XD – nicovell3

+0

但是,那么Java如何序列化和反序列化呢?因为Java使用UTF-8数组来序列化... – nicovell3

+0

@ nicovell3如果字符串序列化调用'String.getBytes(UTF-8)',它将失败。如果它没有失败,它将使用另一种方式转换为UTF-8。 –

0

数组大小也仅限于Integer.MAX_VALUE(这就是为什么String大小是有限的,毕竟有一个char[]支持它),所以这是不可能得到的字节数组,如果编码使用多个字节相比,无论什么String的大小是以字符为单位的。

最终结果将是OutOfMemoryError,但首先创建String会成功。