String ใน Java เป็น immutable class เก็บลำดับตัวอักษร อยู่ในแพ็กเกจ java.lang
String Constant Pool
String literal ทั้งหมด (เช่น "Hello") ถูกเก็บใน String Constant Pool (ส่วนหนึ่งของ Heap) JVM 保证相同內容的字面量只有一個副本
String a = "Hello";
String b = "Hello";
System.out.println(a == b); // true - same reference in pool
แต่ new String("Hello") สร้าง object ใหม่ใน Heap ทุกครั้ง (ไม่อยู่ใน pool)
String a = new String("Hello");
String b = new String("Hello");
System.out.println(a == b); // false - different objects
System.out.println(a.equals(b)); // true - same content
เมธอด intern()
public String intern() คืนค่า reference จาก String Pool:
- ถ้า Pool มี string ที่ equals() แล้ว → คืน reference นั้น
- ถ้าไม่มี → เพิ่ม string นี้เข้า Pool และคืน reference ใหม่
ผลลัพธ์: เรียก intern() บน string ที่มีเนื้อหาเดียวกัน จะได้ reference เดียวกัน (== คืน true)
ตัวอย่าง
public class InternExample {
public static void main(String[] args) {
String str1 = new String("Hello");
str1 = str1.intern(); // เพิ่มใน pool / ดึงจาก pool
String str2 = new String("Hello");
str2 = str2.intern(); // ดึงจาก pool เดียวกัน
System.out.println(str1 == str2); // true!
System.out.println(str1.equals(str2)); // true
}
}
ผลลัพธ์
true
true
เมื่อไหร่ควรใช้ intern()
- Memory optimization: มี string ซ้ำกันเยอะ (เช่น อ่านจากไฟล์/DB, parsing XML/JSON) ใช้ intern() ลด memory
- Performance: การเปรียบเทียบด้วย
==เร็วกว่าequals()มาก (reference comparison) - Canonical representation: ต้องการให้ string เดียวกันมี instance เดียวกันเสมอ
ข้อควรระวัง
- Java 6-: Pool อยู่ใน PermGen (ขนาดจำกัด, อาจ OutOfMemoryError) - ไม่แนะนำ intern() มากเกินไป
- Java 7+: Pool ย้ายไป Heap (มี GC จัดการ) - ใช้ได้ปลอดภัยกว่า
- String literal อยู่ใน pool แล้ว -
"hello".intern()ไม่จำเป็น - Thread-safe แต่มี overhead (synchronized pool)
ตัวอย่างประยุกต์: Deduplication
public class StringDeduplication {
private static final Map pool = new ConcurrentHashMap<>();
public static String internCustom(String s) {
return pool.computeIfAbsent(s, k -> k); // custom pool, ไม่ใช้ JVM pool
}
}
สรุป
| สถานการณ์ | ควรใช้ intern()? |
|---|---|
| String literal | ไม่จำเป็น (อยู่ใน pool แล้ว) |
| new String() จาก external input (เยอะ, ซ้ำ) | ใช่ (Java 7+) |
| String ที่ไม่ซ้ำ/สร้างน้อย | ไม่จำเป็น (overhead ไม่คุ้ม) |
| ต้องการ == comparison | ใช่ (หลัง intern) |