Відповіді:
Зважаючи на те, що Stringклас ' lengthreturn return an int, максимальна довжина, яка повертається методом, буде такою Integer.MAX_VALUE, яка становить 2^31 - 1(або приблизно 2 млрд.)
З точки зору довжини і індексації масивів (наприклад char[], що, ймовірно , так як внутрішнє представлення даних здійснюється для Stringс), Глава 10: Масиви з специфікації мови Java, Java SE 7 Видання говорить наступне:
Змінні, що містяться в масиві, не мають імен; натомість на них посилаються вирази доступу до масиву, які використовують негативні цілочисельні значення індексу. Ці змінні називаються компонентами масиву. Якщо масив має
nкомпоненти, ми говоримо, щоnце довжина масиву; компоненти масиву використовують цілочисельні індекси від0доn - 1включно.
Крім того, індексація повинна бути за intзначеннями, як зазначено у розділі 10.4 :
Масиви повинні бути індексовані
intзначеннями;
Отже, виявляється, що межа дійсно є 2^31 - 1, оскільки це максимальне значення для негативного intзначення.
Однак, ймовірно, будуть інші обмеження, наприклад, максимальний розмір, який можна виділити для масиву.
javacдає помилку з приводу того, що цей javac HelloWorld.java 2>&1|head -c 80 HelloWorld.java:3: constant string too long
javacдля String літералів (не Stringоб'єктів), оскільки я не можу знайти жодних посилань на обмеження розміру для Stringлітералів у специфікації мови Java та специфікації JVM. Я спробував зробити Stringлітерал, розмір якого перевищує 100 000 символів, і у компілятора Eclipse не виникло проблем із його складанням. (І запуск програми зміг показати, що літерал мав String.lengthбільше 100 000.)
java.io.DataInput.readUTF()і java.io.DataOutput.writeUTF(String)кажуть, що Stringоб'єкт представлений двома байтами інформації про довжину та модифікованим представленням UTF-8 кожного символу в рядку. З цього випливає висновок, що довжина String обмежена кількістю байтів модифікованого представлення 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).
Оскільки масиви повинні бути проіндексовані цілими числами, максимальна довжина масиву становить Integer.MAX_INT(2 31 -1, або 2 147 483 647). Це, припускаючи, що у вас є достатньо пам'яті, щоб вмістити масив такого розміру, звичайно.
У мене є 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
Отже, здається, що максимальний розмір масиву становить ~ 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
Отже, здається, що макс є цілим. MAX_VALUE - 2, або (2 ^ 31) - 3
PS Я не впевнений, чому мій StringBuilderмаксимізований, 1207959550а мій - char[](2 ^ 31) -3. Здається, що AbstractStringBuilderвдвічі збільшується внутрішній розмір, char[]щоб виростити його, так що, ймовірно, викликає проблему.
Тип повернення методу length () класу String - це int .
загальна довжина int ()
Зверніться http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#length ()
Отже максимальне значення int становить 2147483647 .
Рядок вважається внутрішнім масивом char, тому індексація проводиться в межах максимального діапазону. Це означає, що ми не можемо індексувати 2147483648-го члена. Отже, максимальна довжина String в Java - 2147483647.
Примітивний тип даних int становить 4 байти (32 біта) в java. Оскільки 1 біт (MSB) використовується як бітовий знак , діапазон обмежений в межах від -2 ^ 31 до 2 ^ 31-1 (-2147483648 до 2147483647). Ми не можемо використовувати негативні значення для індексації. Тому, очевидно, діапазон, який ми можемо використовувати, становить від 0 до 2147483647.
Як згадується у відповіді Такахіко Кавасакі , java представляє рядки Unicode у вигляді модифікованого UTF-8 та в структурі JVM-Spec CONSTANT_UTF8_info , 2 байти виділяються по довжині (а не кількість символів рядка).
Щоб розширити відповідь, на ASM JVM байт - коді бібліотеки putUTF8методи , містить наступне:
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);
}
}
...
}
Але коли зіставлення кодової точки> 1байт, він викликає 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рахувати.
Ви можете знайти модифікований діапазон кодових точок коду Unicode JVM за вказаною вище посиланням utf8.
StringтеоретичноInteger.MAX_VALUE, довжина рядкового літералу у джерелі обмежується лише 65535 байтом даних UTF-8.