Setiap literal "java" yang muncul di kode program tidak serta-merta membuat objek baru saat dieksekusi. JVM mengelola gudang khusus bernama string pool (juga disebut string intern pool): setiap literal String di program ditempatkan di sana tepat satu kali, lalu dipakai bersama oleh semua pemakaian yang isinya sama. Hemat memori yang dihasilkan cukup besar — teks yang sama sering muncul berkali-kali di program nyata. Chapter ini menyelidiki perilaku pool lewat operator ==, membedah perbedaan literal versus new String, lalu memperkenalkan method intern() untuk menyatukan String buatan runtime ke dalam pool.
Literal Bernasib Satu Objek #
Operator == pada variabel referensi membandingkan alamat objek yang ditunjuk, bukan isinya. Sifat tersebut menjadikan == alat ukur yang tepat untuk menyelidiki string pool: bila dua variabel literal menghasilkan == bernilai true, keduanya menunjuk objek yang sama persis di pool.
public class KolamString {
public static void main(String[] args) {
String a = "java";
String b = "java";
String c = new String("java");
String d = c.intern();
System.out.println("a == b : " + (a == b));
System.out.println("a == c : " + (a == c));
System.out.println("a == d : " + (a == d));
System.out.println("hashCode a : " + a.hashCode());
System.out.println("hashCode c : " + c.hashCode());
String gabunganKonstanta = "ja" + "va";
System.out.println("a == \"ja\"+\"va\" : " + (a == gabunganKonstanta));
String bagian = "ja";
String gabunganRuntime = bagian + "va";
System.out.println("a == bagian+\"va\": " + (a == gabunganRuntime));
System.out.println("a == intern() : " + (a == gabunganRuntime.intern()));
}
}Output yang Dihasilkan:
a == b : true
a == c : false
a == d : true
hashCode a : 3254818
hashCode c : 3254818
a == "ja"+"va" : true
a == bagian+"va": false
a == intern() : trueMari kita telaah baris-baris kode di atas:
- Baris 4-5 (
String a = "java"; String b = "java";): literal"java"dijadwalkan compiler masuk pool. Saat JVM memuat class, literal tersebut tinggal satu objek —adanbmenunjuk objek yang sama, dibuktikana == bbernilaitrue. - Baris 6 (
String c = new String("java");): constructornew Stringsecara eksplisit membuat objek baru di heap di luar pool, sekalipun isinya identik. Hasilnyaa == cbernilaifalse— dua objek berbeda dengan isi sama. - Baris 7 (
c.intern()): methodintern()mengembalikan objek dari pool yang isinya sama denganc. Karena"java"sudah ada di pool,dmenunjuk objek yang sama dengana, sehinggaa == dbernilaitrue. - Baris 12-13 (
hashCode): kode hash dihitung dari isi karakter, bukan dari alamat, sehinggaadancmenghasilkan angka yang sama (3254818) meski objeknya berbeda. Inilah sebabnyaHashMapmemakaihashCodedanequals, bukan==. - Baris 15 (
"ja" + "va"): penggabungan dua konstanta dilakukan compiler javac saat kompilasi — hasilnya sudah menjadi literal"java"di pool sebelum program berjalan, sehingga perbandingan bernilaitrue. - Baris 18-19 (
bagian + "va"):bagianadalah variabel, sehingga penggabungan hanya bisa terjadi saat runtime dan menghasilkan objek baru di heap — perbandingan==bernilaifalse. Memanggilintern()pada hasilnya menyatukan kembali ke objek pool, dan perbandingan kembalitrue.
Kapan Pool Bekerja dan Kapan Tidak #
Aturannya dapat dirangkum dalam tabel ringkas berikut.
| Sumber String | Lokasi objek | Menunjuk objek pool? |
|---|---|---|
Literal "java" | string pool | ya |
Konstanta "ja" + "va" | string pool | ya (digabung compiler saat kompilasi) |
new String("java") | heap | tidak |
Penggabungan runtime s + t | heap | tidak (sebelum intern()) |
intern() | string pool | ya |
Yang perlu dicamkan: pool adalah optimasi memori, bukan mekanisme pembandingan isi. Kode yang benar tetap memakai equals() untuk membandingkan isi — pokok bahasan Chapter String Comparison. Pool paling banyak membantu pada teks pendek yang berulang (label, key konfigurasi, nama bulan); teks rakitan runtime yang panjang dan dipakai sekali tidak akan pernah masuk pool kecuali kita memanggil intern() secara sadar, dan memanggil intern() secara massal justru membebani pool itu sendiri.
Pemahaman tentang referensi versus isi kini utuh. Saatnya membahas tiga alat pembanding String dengan peran yang tepat untuk masing-masing: equals untuk isi, == untuk identitas objek, dan compareTo untuk urutan.
Referensi #
- Oracle: Class String (method intern)
- Java Language Specification: Lexical Structure (String Literals)
- dev.java: Learn Java
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
KolamString.java
Unduh berkaspublic class KolamString {
public static void main(String[] args) {
String a = "java";
String b = "java";
String c = new String("java");
String d = c.intern();
System.out.println("a == b : " + (a == b));
System.out.println("a == c : " + (a == c));
System.out.println("a == d : " + (a == d));
System.out.println("hashCode a : " + a.hashCode());
System.out.println("hashCode c : " + c.hashCode());
String gabunganKonstanta = "ja" + "va";
System.out.println("a == \"ja\"+\"va\" : " + (a == gabunganKonstanta));
String bagian = "ja";
String gabunganRuntime = bagian + "va";
System.out.println("a == bagian+\"va\": " + (a == gabunganRuntime));
System.out.println("a == intern() : " + (a == gabunganRuntime.intern()));
}
}