Хотя длина a Stringтеоретически Integer.MAX_VALUE, длина строкового литерала в источнике, по-видимому, ограничена только 65535 байтами данных UTF-8.
200_success
Ответы:
169
Учитывая, что метод Stringкласса lengthвозвращает значение int, максимальная длина, которая будет возвращена методом Integer.MAX_VALUE, будет 2^31 - 1(или приблизительно 2 миллиарда).
Переменные, содержащиеся в массиве, не имеют имен; вместо этого на них ссылаются выражения доступа к массиву, которые используют неотрицательные целочисленные значения индекса. Эти переменные называются
компонентами массива. Если в массиве есть nкомпоненты, мы говорим n:
длина массива; на компоненты массива ссылаются, используя целочисленные индексы от 0до n - 1, включительно.
Кроме того, индексация должна осуществляться по intзначениям, как указано в разделе 10.4 :
Массивы должны быть проиндексированы intзначениями;
Следовательно, представляется, что предел действительно существует 2^31 - 1, поскольку это максимальное значение для неотрицательного intзначения.
Однако, вероятно, будут другие ограничения, такие как максимальный выделяемый размер для массива.
Отличный ответ, человек! Я взглянул на исходный код String.java, и он прав: переменная «count» - это переменная int, которая возвращает длину массива char, а массив char сохраняется в переменной «value» (как char []). что размер строки может быть около 2 ГБ. Конечно, могут быть ограничения для выделения такого объема памяти. Спасибо!
Тайчи
5
Я только что попытался определить строковый литерал в java-программе hello world, которая была длиннее 65546. javacвыдает ошибку, что этот литерал слишком длинный:javac HelloWorld.java 2>&1|head -c 80 HelloWorld.java:3: constant string too long
dlamblin
2
@dlamblin: Это звучит как ограничение javacдля Stringлитералов (не Stringобъектов), поскольку я не могу найти никаких ссылок на ограничения размера Stringлитералов в Спецификации языка Java и Спецификации JVM. Я попытался создать Stringлитерал длиной более 100 000 символов, и у компилятора Eclipse не было проблем с его компиляцией. (И запуск программы смог показать, что у литерала было String.lengthбольше, чем 100 000.)
coobird
3
@Premraj Это было три года назад, поэтому я должен был подумать об этом. ;) Что я имел ввиду; для построения строки максимального размера вам нужно много памяти, возможно, даже больше, чем у вас есть. Вам нужно два байта на символ ~ 4 ГБ, но вы должны построить это из StringBuilder или char [], что означает, что вам нужно еще два байта на символ, чтобы создать его в первую очередь, то есть еще ~ 4 ГБ (по крайней мере, временно)
Питер Лори
25
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];}
Вы можете найти, что размер '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 =newStringBuilder();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 =newchar[Integer.MAX_VALUE - i];Arrays.fill(array,'a');String string =newString(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:2147483647Last:0Requested array size exceeds VM limit
Last:2147483646Last:1Java heap space
Last:2147483645Last:2
Таким образом, кажется, что максимум - Integer.MAX_VALUE - 2 или (2 ^ 31) - 3
PS Я не уверен, почему мой StringBuilderмаксимальный в 1207959550то время как мой char[]максимальный в (2 ^ 31) -3. Кажется, что AbstractStringBuilderудваивает размер его внутреннего, char[]чтобы увеличить его, так что, вероятно, вызывает проблему.
Таким образом, максимальное значение int составляет 2147483647 .
Внутренняя строка считается массивом символов, поэтому индексация выполняется в максимальном диапазоне. Это означает, что мы не можем индексировать 2147483648-й член. Таким образом, максимальная длина строки в java составляет 2147483647.
Примитивный тип данных int составляет 4 байта (32 бита) в java. Поскольку в качестве знакового бита используется 1 бит (MSB) , диапазон ограничен в пределах от -2 ^ 31 до 2 ^ 31-1 (от -2147483648 до 2147483647). Мы не можем использовать отрицательные значения для индексации. Очевидно, что диапазон, который мы можем использовать, составляет от 0 до 2147483647.
publicByteVector putUTF8(finalString stringValue){int charLength = stringValue.length();if(charLength >65535){// If no. of characters> 65535, than however UTF-8 encoded length, wont fit in 2 bytes.thrownewIllegalArgumentException("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метод:
В этом смысле максимальная длина строки составляет 65535 байтов, то есть длина кодировки utf-8. и не в charсчет
Вы можете найти диапазон кодовой точки модифицированного Unicode JVM, из вышеупомянутой ссылки структуры utf8.
String
теоретическиInteger.MAX_VALUE
, длина строкового литерала в источнике, по-видимому, ограничена только 65535 байтами данных UTF-8.Ответы:
Учитывая, что метод
String
классаlength
возвращает значениеint
, максимальная длина, которая будет возвращена методомInteger.MAX_VALUE
, будет2^31 - 1
(или приблизительно 2 миллиарда).С точки зрения длины и индексации массивов (например
char[]
, что, вероятно , так как внутреннее представление данных осуществляется дляString
с), Глава 10: Массивы из спецификации языка Java, Java SE 7 Издание говорит следующее:Кроме того, индексация должна осуществляться по
int
значениям, как указано в разделе 10.4 :Следовательно, представляется, что предел действительно существует
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 представлением каждого символа в строке. Из этого следует, что длина строки ограничена количеством байтов модифицированного представления строки в UTF-8 при использовании сDataInput
иDataOutput
.Кроме того, спецификация
CONSTANT_Utf8_info
найденной в спецификации виртуальной машины Java определяет структуру следующим образом.Вы можете найти, что размер '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 я запустил следующий код:
Это печатает:
Итак, кажется, что максимальный размер массива составляет ~ 1 207 959 549. Затем я понял, что нам на самом деле все равно, не хватает ли Java памяти: мы просто ищем максимальный размер массива (который, кажется, где-то определен как константа). Так:
Какие отпечатки:
Таким образом, кажется, что максимум - Integer.MAX_VALUE - 2 или (2 ^ 31) - 3
PS Я не уверен, почему мой
StringBuilder
максимальный в1207959550
то время как мойchar[]
максимальный в (2 ^ 31) -3. Кажется, чтоAbstractStringBuilder
удваивает размер его внутреннего,char[]
чтобы увеличить его, так что, вероятно, вызывает проблему.источник
по-видимому, он связан с int, который равен 0x7FFFFFFF (2147483647).
источник
Тип возврата метода length () класса String - int .
См. Http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#length ()
Таким образом, максимальное значение int составляет 2147483647 .
Внутренняя строка считается массивом символов, поэтому индексация выполняется в максимальном диапазоне. Это означает, что мы не можем индексировать 2147483648-й член. Таким образом, максимальная длина строки в 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
Но когда отображение кодовой точки> 1 байт, он вызывает
encodeUTF8
метод:В этом смысле максимальная длина строки составляет 65535 байтов, то есть длина кодировки utf-8. и не в
char
счетВы можете найти диапазон кодовой точки модифицированного Unicode JVM, из вышеупомянутой ссылки структуры utf8.
источник