Java 字符串 UTF-8 限制

Java String UTF-8 limits

我正在尝试直接从文件中反序列化字符串,我对超长字符串有疑问:Java 字符串的字符数限制等于 Integer.MAX_VALUE,即 31^2- 1.

但是我的问题来了:当我有一个 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);

是否打印 "String complete!"?还是之前坏过?

数组大小也被限制为Integer.MAX_VALUE(这也是String大小被限制的原因,毕竟有char[]做后盾),所以无法得到字节数组如果编码使用的字节多于此,则无论 String 的字符大小是多少。

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

从根本上说,Strings 的限制是其中的 char 数组不能超过最大数组长度,这大约是 Integer.MAX_VALUE 并且大于您的变量 max。字符串将其字符存储在 UTF-16 中,因此字符串的 UTF-16 表示不能超过最大数组长度。 UTF-8 中的字节数和逻辑字符数(Unicode 代码点,或 UTF-32 字符)最终无关紧要。

现在让我们转到您的特定示例。由于“1234567ñ90”中的 10 个字符中的每一个都是单个 UTF-16 值,因此该字符串占用 Stringchar 数组的 10 个值。尽管您的代码性能糟糕且内存要求高,但如果有足够的可用内存,它最终应该达到 "String complete!"。但是,当转换为 UTF-8 时它会中断,因为字符串的 UTF-8 表示比最大数组长度长,因为“ñ”需要超过一个字节。