답변:
String
클래스의 length
메소드가를 반환한다는 것을 고려하면 int
, 메소드가 반환하는 최대 길이 Integer.MAX_VALUE
는 2^31 - 1
약 20 억입니다.
(예 : 길이와 배열의 색인의 관점에서 char[]
아마도 내부 데이터 표현이 구현되는 방식 인 String
들), 제 10 장 : 배열 의 Java 언어 사양, 자바 SE 7 Edition은 다음을 말한다 :
배열에 포함 된 변수에는 이름이 없습니다. 대신 음이 아닌 정수 인덱스 값을 사용하는 배열 액세스 표현식에 의해 참조됩니다. 이러한 변수를 배열 의 구성 요소 라고합니다 . 배열에
n
구성 요소n
가있는 경우 배열 의 길이 입니다. 배열의 구성 요소는에서0
까지의 정수 색인을 사용하여 참조됩니다n - 1
.
또한 10.4 절int
에서 언급 한 바와 같이 인덱싱은 값을 기준으로 해야합니다 .
배열은
int
값 으로 색인화해야 합니다.
따라서 2^31 - 1
음수가 아닌 최대 값이므로 한계가 실제로 나타납니다.int
값 .
그러나 배열의 할당 가능한 최대 크기와 같은 다른 제한 사항이있을 수 있습니다.
javac
해당 리터럴이 너무 길다는 오류가 발생합니다.javac HelloWorld.java 2>&1|head -c 80 HelloWorld.java:3: constant string too long
javac
대한 제한처럼 들립니다 . 100,000 자보다 큰 리터럴을 만들려고 시도했지만 Eclipse 컴파일러에서 컴파일하는 데 문제가 없었습니다. (그리고 프로그램을 실행하면 리터럴이 100,000보다 큼을 보여줄 수있었습니다 .)String
String
String
String
String.length
java.io.DataInput.readUTF()
및 java.io.DataOutput.writeUTF(String)
있다고 String
객체에 의해 표현되는 두 바이트 길이의 정보의 수정 UTF-8 스트링 내의 각 문자의 표현. 이는 String의 길이가 DataInput
and 와 함께 사용될 때 문자열의 수정 된 UTF-8 표현의 바이트 수에 의해 제한된다는 결론을 내립니다 DataOutput
.
또한, 의 사양CONSTANT_Utf8_info
은 다음과 같이 자바 가상 머신 스펙은 검색된 구조를 정의한다.
CONSTANT_Utf8_info {
u1 tag;
u2 length;
u1 bytes[length];
}
'length'의 크기가 2 바이트 임을 알 수 있습니다 .
특정 방법 (예를 들면의 리턴 타입 그건 String.length()
)이다는 int
항상 허용되는 최대 값입니다 의미하지 않는다 Integer.MAX_VALUE
. 대신 대부분의 경우 int
성능상의 이유로 선택됩니다. Java 언어 사양에 따르면 크기가 정수보다 작은 정수는 계산 전에 int
변환됩니다 int
(메모리가 올바르게 제공 int
되는 경우) 특별한 이유가없는 경우 선택 해야하는 이유 중 하나 입니다.
컴파일 타임의 최대 길이는 최대 65536입니다. 길이는 오브젝트 의 문자 수가 아니라 수정 된 UTF-8 표현 의 바이트 수입니다 String
.
String
객체는 런타임에 훨씬 더 많은 문자를 가질 수 있습니다. 사용할 경우, String
와 객체 DataInput
및 DataOutput
인터페이스를 너무 오래 사용하지 않는 것이 좋습니다 String
객체. 이 I-C의 목표 등가물을 구현할 때이 제한을 발견 DataInput.readUTF()
하고 DataOutput.writeUTF(String)
.
Java 1.8.0_25와 함께 Eclipse Neon.2 릴리스 (4.6.2)를 실행하는 8GB RAM의 2010 iMac이 있습니다. 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[]
커져서 문제가되는 것 같습니다.
String 클래스의 length () 메소드의 리턴 유형은 int 입니다.
공개 int 길이 ()
보내다 http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#length ()를 하십시오.
따라서 int의 최대 값은 2147483647 입니다.
문자열은 내부적으로 char 배열로 간주되므로 인덱싱은 최대 범위 내에서 수행됩니다. 이것은 우리가 2147483648 번째 멤버를 인덱스 할 수 없다는 것을 의미합니다. 따라서 자바에서 String의 최대 길이는 2147483647입니다.
기본 데이터 유형 int는 java에서 4 바이트 (32 비트)입니다. 1 비트 (MSB)가 부호 비트로 사용되므로 범위는 -2 ^ 31에서 2 ^ 31-1 (-2147483648에서 2147483647)로 제한됩니다. 인덱싱에 음수 값을 사용할 수 없으므로 사용할 수있는 범위는 0에서 2147483647 사이입니다.
Takahiko Kawasaki의 답변 에서 언급했듯이 java는 수정 된 UTF-8 형식의 유니 코드 문자열을 나타내며 JVM 사양 CONSTANT_UTF8_info Structure 에서 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
카운트
당신은 위의 UTF8 구조체 링크에서, JVM의 수정 된 유니 코드 코드 포인트 범위를 찾을 수 있습니다.
String
는 이론적으로Integer.MAX_VALUE
이지만 소스의 문자열 리터럴 길이는 65535 바이트 의 UTF-8 데이터 로만 제한되는 것으로 보입니다 .