เมธอด intern() ของ String Class ใช้แก้ปัญหา String Duplication ประหยัดหน่วยความจำจาก Duplicate String Instances (เนื้อหาเหมือนกัน แต่อยู่คนละ Memory Location)
String Pool และ intern()
- JVM มี String Pool (ใน Heap) เก็บ String Literal
- String Literal เดียวกัน → ชี้ Object เดียวใน Pool
- new String() สร้าง Object ใหม่เสมอ แม้ค่าเหมือน Literal ใน Pool
- intern() บังคับให้ JVM คืน Reference จาก Pool (ถ้ามี) หรือเพิ่มเข้า Pool (ถ้ายังไม่มี)
เมื่อไหร่ควรใช้ intern()?
- สร้าง String ด้วย new String() แล้วต้องการเปรียบเทียบด้วย == (Reference Equality)
- มี String จำนวนมากที่ซ้ำกัน (เช่น อ่านจากไฟล์/Database) ต้องการ deduplicate
- Memory-sensitive Application ที่ต้องการลด Heap Usage
ตัวอย่างโค้ด
public class StringInternClassTest {
public static void main(String[] args) {
String s1 = "Tutorix"; // Literal - ใน Pool
String s2 = "Tutorix"; // Literal - เดียวกับ s1
String s3 = new String("Tutorix"); // Heap Object ใหม่
String s4 = s3.intern(); // บังคับดึงจาก Pool
String s5 = "?Tutorix".substring(1); // Runtime String
String s6 = s5.intern(); // intern() รันไทม์
// == Comparison (Reference)
System.out.println(s1 == s2); // true (Same Pool Ref)
System.out.println(s2 == s3); // false (Literal vs new Object)
System.out.println(s3 == s4); // false (new Object vs Pooled)
System.out.println(s1 == s3); // false
System.out.println(s1 == s4); // true (Both from Pool)
System.out.println(s1 == s5); // false (Runtime String)
System.out.println(s1 == s6); // true (Interned)
// .equals() Comparison (Value)
System.out.println(s1.equals(s2)); // true
System.out.println(s2.equals(s3)); // true
System.out.println(s3.equals(s4)); // true
System.out.println(s1.equals(s4)); // true
System.out.println(s1.equals(s3)); // true
}
}
ผลลัพธ์
true
false
false
false
true
false
true
true
true
true
true
true
ข้อควรระวัง
- intern() มี Overhead (Hash lookup, Lock contention ใน Pool)
- Java 7+ String Pool อยู่ใน Heap (PermGen → Metaspace → Heap)
- ใช้ profiling ก่อนตัดสินใจ (ไม่ใช่ Silver Bullet)
- ปกติใช้ .equals() เปรียบเทียบค่า ไม่ต้อง intern()