Apa itu String Interning di Jawa, kapan saya harus menggunakannya, dan mengapa ?
java
string
string-interning
saplingPro
sumber
sumber
String a = new String("abc");
String b = new String("abc");
thena.intern() == b.intern()
String.intern()
tergantung padaClassLoader
, artinya, Apakah classloader yang berbeda menciptakan "berbeda"String
, menyebabkan perbedaanintern
?Jawaban:
http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#intern ()
Pada dasarnya melakukan String.intern () pada serangkaian string akan memastikan bahwa semua string yang memiliki konten yang sama memiliki memori yang sama. Jadi jika Anda memiliki daftar nama tempat 'john' muncul 1000 kali, dengan magang Anda memastikan hanya satu 'john' yang benar-benar dialokasikan memori.
Ini dapat berguna untuk mengurangi kebutuhan memori program Anda. Namun perlu diingat bahwa cache dikelola oleh JVM di memori permanen yang biasanya terbatas dalam ukuran dibandingkan dengan tumpukan sehingga Anda tidak boleh menggunakan intern jika Anda tidak memiliki terlalu banyak nilai duplikat.
Lebih lanjut tentang kendala memori menggunakan intern ()
- Dari: http://www.codeinstructions.com/2009/01/busting-javalangstringintern-myths.html
Dari JDK 7 (maksud saya di HotSpot), ada sesuatu yang berubah.
- Dari Java SE 7 Fitur dan Peningkatan
Pembaruan: String magang disimpan di tumpukan utama dari Java 7 dan seterusnya. http://www.oracle.com/technetwork/java/javase/jdk7-relnotes-418459.html#jdk7changes
sumber
char[]
alih-alihString
untuk teks sensitif dan nolkan segera setelah itu tidak lagi diperlukan.Ada beberapa pertanyaan "wawancara menarik", seperti mengapa Anda mendapatkan yang sama! jika Anda mengeksekusi potongan kode di bawah ini.
Jika Anda ingin membandingkan Strings yang harus Anda gunakan
equals()
. Di atas akan mencetak sama dengan karenatestString
sudah diinternir untuk Anda oleh kompiler. Anda dapat menginternir string sendiri menggunakan metode intern seperti yang ditunjukkan dalam jawaban sebelumnya ....sumber
equals
metode ini. Anda mungkin ingin menambahkannew String()
perbandingan untuk menunjukkan perbedaan lebih jelas.JLS
JLS 7 3.10.5 mendefinisikannya dan memberikan contoh praktis:
JVMS
JVMS 7 5.1 mengatakan bahwa interning diimplementasikan secara ajaib dan efisien dengan
CONSTANT_String_info
struct khusus (tidak seperti kebanyakan objek lain yang memiliki representasi lebih umum):Bytecode
Mari kita mendekompilasi beberapa bytecode OpenJDK 7 untuk melihat tindakan interning.
Jika kami mendekompilasi:
yang kita miliki di kolam konstan:
dan
main
:Perhatikan caranya:
0
dan3
:ldc #2
konstanta yang sama dimuat (literal)12
: contoh string baru dibuat (dengan#2
sebagai argumen)35
:a
danc
dibandingkan sebagai objek biasa denganif_acmpne
Representasi string konstan cukup ajaib pada bytecode:
new String
)dan kutipan JVMS di atas tampaknya mengatakan bahwa setiap kali Utf8 menunjuk adalah sama, maka instance identik dimuat oleh
ldc
.Saya telah melakukan tes serupa untuk bidang, dan:
static final String s = "abc"
menunjuk ke tabel konstan melalui Atribut ConstantValueldc
Kesimpulan : ada dukungan bytecode langsung untuk kumpulan string, dan representasi memori efisien.
Bonus: bandingkan dengan kelompok Integer , yang tidak memiliki dukungan bytecode langsung (yaitu tidak ada
CONSTANT_String_info
analog).sumber
Pembaruan untuk Java 8 atau plus . Di Java 8, ruang PermGen (Generasi Permanen) dihapus dan diganti oleh Meta Space. Memori kumpulan string dipindahkan ke tumpukan JVM.
Dibandingkan dengan Java 7, ukuran string pool bertambah di heap. Oleh karena itu, Anda memiliki lebih banyak ruang untuk Strings yang terinternalisasi, tetapi Anda memiliki lebih sedikit memori untuk seluruh aplikasi.
Satu hal lagi, Anda sudah tahu bahwa ketika membandingkan 2 (rujukan) objek di Jawa, '
==
' digunakan untuk membandingkan referensi objek, 'equals
' digunakan untuk membandingkan konten objek.Mari kita periksa kode ini:
Hasil:
value1 == value2
---> benarvalue1 == value3
---> salahvalue1.equals(value3)
---> benarvalue1 == value3.intern()
---> benarItu sebabnya Anda harus menggunakan '
equals
' untuk membandingkan 2 objek String. Dan itulah caraintern()
berguna.sumber
String interning adalah teknik optimisasi oleh kompiler. Jika Anda memiliki dua literal string identik dalam satu unit kompilasi maka kode yang dihasilkan memastikan bahwa hanya ada satu objek string yang dibuat untuk semua instance dari literal itu (karakter terlampir dalam tanda kutip ganda) di dalam rakitan.
Saya dari latar belakang C #, jadi saya bisa menjelaskan dengan memberikan contoh dari itu:
output dari perbandingan berikut:
Catatan1 : Objek dibandingkan dengan referensi.
Note2 : typeof (int). Nama dievaluasi dengan metode refleksi sehingga tidak dievaluasi pada waktu kompilasi. Di sini perbandingan ini dibuat pada waktu kompilasi.
Analisis Hasil: 1) benar karena keduanya mengandung literal yang sama dan kode yang dihasilkan hanya akan memiliki satu objek referensi "Int32". Lihat Catatan 1 .
2) benar karena isi dari kedua nilai diperiksa yang sama.
3) FALSE karena str2 dan obj tidak memiliki literal yang sama. Lihat Catatan 2 .
sumber
sumber
Dari buku Deshmukh Programmer OCP Java SE 11 saya menemukan penjelasan termudah untuk Interning yang mengikuti sebagai berikut: Karena string adalah objek dan karena semua objek di Jawa selalu disimpan hanya dalam ruang heap, semua string disimpan dalam ruang heap. Namun, Java menyimpan string yang dibuat tanpa menggunakan kata kunci baru di area khusus ruang heap, yang disebut "string pool". Java menyimpan string yang dibuat menggunakan kata kunci baru di ruang heap biasa.
Tujuan dari kumpulan string adalah untuk mempertahankan serangkaian string unik. Setiap kali Anda membuat string baru tanpa menggunakan kata kunci baru, Java memeriksa apakah string yang sama sudah ada di kumpulan string. Jika ya, Java mengembalikan referensi ke objek String yang sama dan jika tidak, Java membuat objek String baru di kumpulan string dan mengembalikan referensi. Jadi, misalnya, jika Anda menggunakan string "halo" dua kali dalam kode Anda seperti yang ditunjukkan di bawah ini, Anda akan mendapatkan referensi ke string yang sama. Kami benar-benar dapat menguji teori ini dengan membandingkan dua variabel referensi yang berbeda menggunakan operator == seperti yang ditunjukkan dalam kode berikut:
== operator hanya memeriksa apakah dua referensi menunjuk ke objek yang sama atau tidak dan mengembalikan true jika mereka. Dalam kode di atas, str2 mendapatkan referensi ke objek String yang sama yang telah dibuat sebelumnya. Namun, str3 dan STR4 mendapatkan referensi ke dua objek String yang sama sekali berbeda. Itulah sebabnya str1 == str2 pengembalian benar tetapi str1 == str3 dan str3 == STR4 kembali palsu. Bahkan, ketika Anda melakukan String baru ("halo"); dua objek String dibuat bukan hanya satu jika ini adalah pertama kalinya string "halo" digunakan di mana saja dalam program - satu di kumpulan string karena penggunaan string yang dikutip, dan satu di ruang tumpukan reguler karena penggunaan kata kunci baru.
Penyatuan string adalah cara Java menyimpan memori program dengan menghindari pembuatan beberapa objek String yang berisi nilai yang sama. Dimungkinkan untuk mendapatkan string dari kumpulan string untuk string yang dibuat menggunakan kata kunci baru dengan menggunakan metode intern String. Ini disebut "magang" objek string. Sebagai contoh,
sumber