Jawaban:
Mempertimbangkan metode String
kelas length
mengembalikan suatu int
, panjang maksimum yang akan dikembalikan oleh metode adalah Integer.MAX_VALUE
, yaitu 2^31 - 1
(atau sekitar 2 miliar).
Dalam hal panjang dan pengindeksan array, (seperti char[]
, yang mungkin adalah cara internal representasi data diimplementasikan untuk String
s), Bab 10: Array of The Java Language Specification, Java SE 7 Edition mengatakan sebagai berikut:
Variabel yang terkandung dalam array tidak memiliki nama; sebaliknya mereka direferensikan oleh ekspresi akses array yang menggunakan nilai indeks integer nonnegatif. Variabel-variabel ini disebut komponen - komponen array. Jika sebuah array memiliki
n
komponen, kita katakann
adalah panjang array; komponen-komponen array direferensikan menggunakan indeks integer dari0
hinggan - 1
, inklusif.
Selanjutnya, pengindeksan harus berdasarkan int
nilai, seperti yang disebutkan dalam Bagian 10.4 :
Array harus diindeks oleh
int
nilai;
Oleh karena itu, tampaknya batasnya memang 2^31 - 1
, karena itu adalah nilai maksimum untuk nilai bukan negatif int
.
Namun, mungkin akan ada batasan lain, seperti ukuran maksimum yang dapat dialokasikan untuk sebuah array.
javac
memberikan kesalahan tentang literal yang terlalu panjang:javac HelloWorld.java 2>&1|head -c 80 HelloWorld.java:3: constant string too long
javac
untuk String
literal (bukan String
objek), karena saya tidak dapat menemukan referensi untuk batas ukuran String
literal dalam Spesifikasi Bahasa Jawa dan Spesifikasi JVM. Saya mencoba membuat String
literal yang lebih besar dari 100.000 karakter, dan kompiler Eclipse tidak memiliki masalah dalam mengkompilasinya. (Dan menjalankan program ini dapat menunjukkan bahwa literal memiliki String.length
lebih dari 100.000.)
java.io.DataInput.readUTF()
dan java.io.DataOutput.writeUTF(String)
mengatakan bahwa String
objek diwakili oleh dua byte informasi panjang dan representasi UTF-8 yang dimodifikasi dari setiap karakter dalam string. Ini menyimpulkan bahwa panjang String dibatasi oleh jumlah byte dari representasi UTF-8 yang dimodifikasi dari string ketika digunakan dengan DataInput
dan DataOutput
.
Selain itu, Spesifikasi yangCONSTANT_Utf8_info
ditemukan dalam spesifikasi mesin virtual Java mendefinisikan struktur sebagai berikut.
CONSTANT_Utf8_info {
u1 tag;
u2 length;
u1 bytes[length];
}
Anda dapat menemukan bahwa ukuran 'panjang' adalah dua byte .
Bahwa tipe pengembalian dari metode tertentu (misalnya String.length()
) int
tidak selalu berarti bahwa nilai maksimum yang diizinkan adalah Integer.MAX_VALUE
. Sebaliknya, dalam banyak kasus, int
dipilih hanya karena alasan kinerja. Spesifikasi bahasa Java mengatakan bahwa bilangan bulat yang ukurannya lebih kecil daripada yang int
dikonversi int
sebelum perhitungan (jika ingatanku benar) dan itu adalah salah satu alasan untuk memilih int
ketika tidak ada alasan khusus.
Panjang maksimum pada waktu kompilasi paling banyak 65.536. Perhatikan lagi bahwa panjangnya adalah jumlah byte dari representasi UTF-8 yang dimodifikasi , bukan jumlah karakter dalam String
objek.
String
objek mungkin dapat memiliki lebih banyak karakter saat runtime. Namun, jika Anda ingin menggunakan String
objek dengan DataInput
dan DataOutput
antarmuka, lebih baik untuk menghindari menggunakan objek yang terlalu panjang String
. Saya menemukan batasan ini ketika saya menerapkan setara Objective-C dari DataInput.readUTF()
dan DataOutput.writeUTF(String)
.
Karena array harus diindeks dengan bilangan bulat, panjang maksimum array adalah Integer.MAX_INT
(2 31 -1, atau 2 147 483 647). Ini dengan asumsi Anda memiliki cukup memori untuk menyimpan array ukuran itu, tentu saja.
Saya memiliki iMac 2010 dengan 8GB RAM, menjalankan Eclipse Neon.2 Release (4.6.2) dengan Java 1.8.0_25. Dengan argumen VM -Xmx6g, saya menjalankan kode berikut:
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());
Ini mencetak:
Requested array size exceeds VM limit
1207959550
Jadi, tampaknya ukuran array maksimum adalah ~ 1.207.959.549. Kemudian saya menyadari bahwa kita sebenarnya tidak peduli jika Java kehabisan memori: kita hanya mencari ukuran array maksimum (yang tampaknya merupakan konstanta yang didefinisikan di suatu tempat). Begitu:
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);
}
}
Yang mencetak:
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
Jadi, sepertinya maks adalah Integer.MAX_VALUE - 2, atau (2 ^ 31) - 3
PS Saya tidak yakin mengapa saya StringBuilder
maxed out 1207959550
sementara char[]
maxed out saya di (2 ^ 31) -3. Tampaknya AbstractStringBuilder
menggandakan ukuran internal char[]
untuk menumbuhkannya, sehingga mungkin menyebabkan masalah.
Tipe Return dari metode length () dari kelas String adalah int .
panjang int publik ()
Rujuk http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#length ()
Jadi nilai maksimum int adalah 2147483647 .
String dianggap sebagai array char secara internal, Jadi pengindeksan dilakukan dalam rentang maksimum. Ini berarti kita tidak dapat mengindeks anggota 2147483648. Jadi panjang maksimum String di java adalah 2147483647.
Int tipe data primitif adalah 4 byte (32 bit) di java. As 1 bit (MSB) digunakan sebagai bit tanda , Kisarannya dibatasi dalam -2 ^ 31 hingga 2 ^ 31-1 (-2147483648 hingga 2147483647). Kami tidak dapat menggunakan nilai negatif untuk pengindeksan. Jadi jelas rentang yang dapat kami gunakan adalah dari 0 hingga 2147483647.
Seperti yang disebutkan dalam jawaban Takahiko Kawasaki , java mewakili string Unicode dalam bentuk UTF-8 yang dimodifikasi dan dalam Struktur JVM-Spec CONSTANT_UTF8_info , 2 byte dialokasikan untuk panjang (dan bukan jumlah karakter String).
Untuk memperluas jawabannya, metode pustaka bytecode ASM jvm , berisi ini: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);
}
}
...
}
Tetapi ketika pemetaan kode-titik> 1byte, ia memanggil encodeUTF8
metode:
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;
}
}
...
}
Dalam pengertian ini, panjang string maks adalah 65535 byte, yaitu panjang enkode utf-8. dan tidak char
masuk hitungan
Anda dapat menemukan rentang kode-titik Unicode yang dimodifikasi dari JVM, dari tautan struct utf8 di atas.
String
secara teoritisInteger.MAX_VALUE
, panjang string literal di sumber tampaknya terbatas hanya 65535 byte data UTF-8.