Мой вопрос очень простой, но я не нашел ответа на поиск в Google.
В Java, каков максимальный размер объекта String
, ссылаясь на вызов метода length()
?
Я знаю, что length()
возвращает размер String
как char []
;
Мой вопрос очень простой, но я не нашел ответа на поиск в Google.
В Java, каков максимальный размер объекта String
, ссылаясь на вызов метода length()
?
Я знаю, что length()
возвращает размер String
как char []
;
Учитывая String
class 'length
возвращает int
, максимальная длина, возвращаемая методом, будет Integer.MAX_VALUE
, которая равна 2^31 - 1
(или около 2 миллиардов.)
В терминах длины и индексации массивов (например, char[]
, что, вероятно, является способом представления внутренних данных для String
s), Глава 10: Массивы Спецификация Java Language, Java SE 7 Edition гласит следующее:
Переменные, содержащиеся в массиве не имеют имен; вместо этого они ссылки на выражения доступа к массиву которые используют неотрицательный целочисленный индекс значения. Эти переменные называются компоненты массива. Если массив имеет компоненты
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
представлен двумя байтами информации о длине и измененным UTF-8 представление каждого символа в строке. Это делает вывод о том, что длина строки ограничена количеством байтов модифицированного представления строки UTF-8 при использовании с DataInput
и DataOutput
.
Кроме того, Спецификация CONSTANT_Utf8_info
, найденная в спецификации виртуальной машины Java, определяет структуру следующим образом.
CONSTANT_Utf8_info {
u1 tag;
u2 length;
u1 bytes[length];
}
Вы можете найти, что размер "длина" два байта.
То, что тип возврата определенного метода (например, String.length()
) составляет int
, не всегда означает, что его допустимое максимальное значение равно Integer.MAX_VALUE
. Вместо этого, в большинстве случаев, int
выбирается только по соображениям производительности. Спецификация языка Java говорит, что целые числа, размер которых меньше, чем int
, преобразуются в int
перед вычислением (если моя память служит мне правильно), и это одна из причин выбора int
, когда нет особой причины.
Максимальная длина во время компиляции не более 65536. Заметим еще раз, что длина представляет собой количество байтов измененного представления UTF-8, а не количество символов в объекте String
.
String
объекты могут иметь гораздо больше символов во время выполнения. Однако, если вы хотите использовать объекты String
с интерфейсами DataInput
и DataOutput
, лучше избегать использования слишком длинных объектов String
. Я нашел это ограничение, когда я внедрил Objective-C эквиваленты DataInput.readUTF()
и DataOutput.writeUTF(String)
.
по-видимому, он связан с int, который равен 0x7FFFFFFF (2147483647).
Тип возвращаемого значения метода length() класса String int.
public int length()
Обратитесь http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#length()
Таким образом, максимальное значение int 2147483647.
Строка считается внутренним массивом char, поэтому индексирование выполняется в пределах максимального диапазона. Это означает, что мы не можем индексировать 2147483648-й член. Таким образом, максимальная длина строки в java равна 2147483647.
Примитивный тип данных int - 4 байта (32 бита) в java. В качестве знакового бита используется 1 бит (MSB). Диапазон ограничен в пределах от -2 ^ 31 до 2 ^ 31-1 (-2147483648 до 2147483647).). Мы не можем использовать отрицательные значения для индексации. Очевидно, что диапазон, который мы можем использовать, составляет от 0 до 2147483647.
У меня есть iMac 2010 года с 8 ГБ ОЗУ, запускающий Eclipse Neon.2 Release (4.6.2) с Java 1.8.0_25. С аргументом 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
Итак, кажется, что максимальный размер массива составляет ~ 1207,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
Итак, кажется, что max является Integer.MAX_VALUE - 2, или (2 ^ 31) - 3
P.S. Я не уверен, почему мой StringBuilder
достиг максимума в 1207959550
, а мой char[]
превысил отметку (2 ^ 31) -3. Кажется, что AbstractStringBuilder
удваивает размер своего внутреннего char[]
, чтобы увеличить его, что, вероятно, вызывает проблему.