Sementara panjang a Stringsecara teoritis Integer.MAX_VALUE, panjang string literal di sumber tampaknya terbatas hanya 65535 byte data UTF-8.
200_sukses
Jawaban:
169
Mempertimbangkan metode Stringkelas lengthmengembalikan suatu int, panjang maksimum yang akan dikembalikan oleh metode adalah Integer.MAX_VALUE, yaitu 2^31 - 1(atau sekitar 2 miliar).
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 nkomponen, kita katakan nadalah
panjang array; komponen-komponen array direferensikan menggunakan indeks integer dari 0hingga n - 1, inklusif.
Selanjutnya, pengindeksan harus berdasarkan intnilai, seperti yang disebutkan dalam Bagian 10.4 :
Array harus diindeks oleh intnilai;
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.
Jawaban yang bagus! Saya melihat pada kode sumber String.java dan benar, 'count' adalah variabel int yang mengembalikan panjang array char, dan array char disimpan pada variabel 'value' (as char []) Ini berarti bahwa ukuran String bisa sekitar 2GB. Tentu saja mungkin ada batasan untuk mengalokasikan ukuran memori tersebut. Terima kasih!
taichi
5
Saya baru saja mencoba mendefinisikan string literal dalam program hello world java yang lebih panjang dari 65546. javacmemberikan kesalahan tentang literal yang terlalu panjang:javac HelloWorld.java 2>&1|head -c 80 HelloWorld.java:3: constant string too long
dlamblin
2
@ dlamblin: Kedengarannya seperti batasan javacuntuk Stringliteral (bukan Stringobjek), karena saya tidak dapat menemukan referensi untuk batas ukuran Stringliteral dalam Spesifikasi Bahasa Jawa dan Spesifikasi JVM. Saya mencoba membuat Stringliteral 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.lengthlebih dari 100.000.)
coobird
3
@ Primraj Itu tiga tahun lalu jadi saya harus memikirkannya. ;) Yang saya maksud adalah; untuk membangun string berukuran maksimum, Anda perlu banyak memori, mungkin lebih dari yang Anda miliki. Anda memerlukan dua byte per karakter ~ 4GB, tetapi Anda harus membuatnya dari StringBuilder atau char [] yang artinya Anda memerlukan dua byte per karakter untuk membuatnya terlebih dahulu, yaitu yang lain ~ 4 GB (setidaknya sementara)
Peter Lawrey
25
java.io.DataInput.readUTF()dan java.io.DataOutput.writeUTF(String)mengatakan bahwa Stringobjek 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 DataInputdan DataOutput.
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()) inttidak selalu berarti bahwa nilai maksimum yang diizinkan adalah Integer.MAX_VALUE. Sebaliknya, dalam banyak kasus, intdipilih hanya karena alasan kinerja. Spesifikasi bahasa Java mengatakan bahwa bilangan bulat yang ukurannya lebih kecil daripada yang intdikonversi intsebelum perhitungan (jika ingatanku benar) dan itu adalah salah satu alasan untuk memilih intketika 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 Stringobjek.
Stringobjek mungkin dapat memiliki lebih banyak karakter saat runtime. Namun, jika Anda ingin menggunakan Stringobjek dengan DataInputdan DataOutputantarmuka, 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 =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());
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 =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);}}
Yang mencetak:
Requested array size exceeds VM limit
Last:2147483647Last:0Requested array size exceeds VM limit
Last:2147483646Last:1Java heap space
Last:2147483645Last:2
Jadi, sepertinya maks adalah Integer.MAX_VALUE - 2, atau (2 ^ 31) - 3
PS Saya tidak yakin mengapa saya StringBuildermaxed out 1207959550sementara char[]maxed out saya di (2 ^ 31) -3. Tampaknya AbstractStringBuildermenggandakan ukuran internal char[]untuk menumbuhkannya, sehingga mungkin menyebabkan masalah.
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.
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);}}...}
Tetapi ketika pemetaan kode-titik> 1byte, ia memanggil encodeUTF8metode:
Dalam pengertian ini, panjang string maks adalah 65535 byte, yaitu panjang enkode utf-8. dan tidak charmasuk 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.Jawaban:
Mempertimbangkan metode
String
kelaslength
mengembalikan suatuint
, panjang maksimum yang akan dikembalikan oleh metode adalahInteger.MAX_VALUE
, yaitu2^31 - 1
(atau sekitar 2 miliar).Dalam hal panjang dan pengindeksan array, (seperti
char[]
, yang mungkin adalah cara internal representasi data diimplementasikan untukString
s), Bab 10: Array of The Java Language Specification, Java SE 7 Edition mengatakan sebagai berikut:Selanjutnya, pengindeksan harus berdasarkan
int
nilai, seperti yang disebutkan dalam Bagian 10.4 :Oleh karena itu, tampaknya batasnya memang
2^31 - 1
, karena itu adalah nilai maksimum untuk nilai bukan negatifint
.Namun, mungkin akan ada batasan lain, seperti ukuran maksimum yang dapat dialokasikan untuk sebuah array.
sumber
javac
memberikan kesalahan tentang literal yang terlalu panjang:javac HelloWorld.java 2>&1|head -c 80 HelloWorld.java:3: constant string too long
javac
untukString
literal (bukanString
objek), karena saya tidak dapat menemukan referensi untuk batas ukuranString
literal dalam Spesifikasi Bahasa Jawa dan Spesifikasi JVM. Saya mencoba membuatString
literal yang lebih besar dari 100.000 karakter, dan kompiler Eclipse tidak memiliki masalah dalam mengkompilasinya. (Dan menjalankan program ini dapat menunjukkan bahwa literal memilikiString.length
lebih dari 100.000.)java.io.DataInput.readUTF()
danjava.io.DataOutput.writeUTF(String)
mengatakan bahwaString
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 denganDataInput
danDataOutput
.Selain itu, Spesifikasi yang
CONSTANT_Utf8_info
ditemukan dalam spesifikasi mesin virtual Java mendefinisikan struktur sebagai berikut.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 adalahInteger.MAX_VALUE
. Sebaliknya, dalam banyak kasus,int
dipilih hanya karena alasan kinerja. Spesifikasi bahasa Java mengatakan bahwa bilangan bulat yang ukurannya lebih kecil daripada yangint
dikonversiint
sebelum perhitungan (jika ingatanku benar) dan itu adalah salah satu alasan untuk memilihint
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 menggunakanString
objek denganDataInput
danDataOutput
antarmuka, lebih baik untuk menghindari menggunakan objek yang terlalu panjangString
. Saya menemukan batasan ini ketika saya menerapkan setara Objective-C dariDataInput.readUTF()
danDataOutput.writeUTF(String)
.sumber
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.sumber
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:
Ini mencetak:
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:
Yang mencetak:
Jadi, sepertinya maks adalah Integer.MAX_VALUE - 2, atau (2 ^ 31) - 3
PS Saya tidak yakin mengapa saya
StringBuilder
maxed out1207959550
sementarachar[]
maxed out saya di (2 ^ 31) -3. TampaknyaAbstractStringBuilder
menggandakan ukuran internalchar[]
untuk menumbuhkannya, sehingga mungkin menyebabkan masalah.sumber
rupanya itu terikat ke int, yaitu 0x7FFFFFFF (2147483647).
sumber
Tipe Return dari metode length () dari kelas String adalah int .
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.
sumber
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
Tetapi ketika pemetaan kode-titik> 1byte, ia memanggil
encodeUTF8
metode:Dalam pengertian ini, panjang string maks adalah 65535 byte, yaitu panjang enkode utf-8. dan tidak
char
masuk hitunganAnda dapat menemukan rentang kode-titik Unicode yang dimodifikasi dari JVM, dari tautan struct utf8 di atas.
sumber