String.intern() trả về tham chiếu đến instance trong String Pool (chuỗi nội bộ). Giúp tiết kiệm bộ nhớ khi nhiều chuỗi trùng lặp.
Cơ chế String Pool
- String literal (
"abc") tự động vào pool new String("abc")tạo object mới trên heap, KHÔNG vào poolintern(): nếu pool đã có chuỗi bằngequals(), trả về reference pool; ngược lại thêm vào pool và trả về reference mới
Ví dụ minh họa
public class InternDemo {
public static void main(String[] args) {
String s1 = new String("Hello"); // heap object
String s2 = "Hello"; // pool object
String s3 = new String("Hello"); // heap object khác
System.out.println("s1 == s2: " + (s1 == s2)); // false (khác object)
System.out.println("s1.equals(s2): " + s1.equals(s2)); // true
// Sau intern()
String i1 = s1.intern(); // trả về pool reference (s2)
String i2 = s2.intern(); // trả về pool reference (s2)
String i3 = s3.intern(); // trả về pool reference (s2)
System.out.println("i1 == i2: " + (i1 == i2)); // true
System.out.println("i1 == s2: " + (i1 == s2)); // true
System.out.println("i3 == s2: " + (i3 == s2)); // true
}
}
Kết quả
s1 == s2: false
s1.equals(s2): true
i1 == i2: true
i1 == s2: true
i3 == s2: true
Khi nào dùng intern()?
- Nhiều chuỗi trùng lặp (ví dụ: đọc file log, tên thành phố, từ điển)
- So sánh bằng
==thay vìequals()(nhanh hơn, nhưng nguy hiểm nếu quên intern) - Giảm memory footprint
⚠️ Cảnh báo
- Java 7+: String pool chuyển từ PermGen (fixed size) sang Heap – an toàn hơn nhưng vẫn có overhead
- Lạm dụng intern() → pool quá lớn → GC chậm, thậm chí OOM
- Không dùng intern() cho input user không tin cậy (DoS vector)
- So sánh chuỗi: luôn dùng equals(), chỉ dùng == khi chắc chắn đã intern()
Alternatives hiện đại
- Dùng
StringBuilderbuild chuỗi, không cần intern - Dùng
Map<String, String>cache thủ công (weak reference) - JVM option:
-XX:StringTableSize=Ntùy chỉnh pool size