स्ट्रिंग इम्यूटेबल (immutable) का अर्थ है कि हम ऑब्जेक्ट को स्वयं नहीं बदल सकते, लेकिन हम ऑब्जेक्ट के रेफरेंस को बदल सकते हैं। स्ट्रिंग को final बनाया गया है ताकि कोई इसे एक्सटेंड न कर सके और इसकी इम्यूटेबिलिटी को नष्ट न कर सके।
String के इम्यूटेबल/फाइनल होने के कारण
1. सुरक्षा (Security)
पैरामीटर्स आमतौर पर नेटवर्क कनेक्शन, डेटाबेस कनेक्शन URL, यूजरनेम/पासवर्ड आदि में स्ट्रिंग के रूप में दर्शाए जाते हैं। यदि यह म्यूटेबल होता, तो इन पैरामीटर्स को आसानी से बदला जा सकता था, जिससे सुरक्षा भंग हो सकती है।
2. सिंक्रोनाइजेशन और कनकरेंसी (Synchronization and Concurrency)
स्ट्रिंग को इम्यूटेबल बनाने से वे स्वचालित रूप से थ्रेड-सेफ हो जाते हैं, जिससे सिंक्रोनाइजेशन समस्याएं हल हो जाती हैं। एकाधिक थ्रेड्स एक ही स्ट्रिंग ऑब्जेक्ट को बिना किसी लॉक के सुरक्षित रूप से साझा कर सकते हैं।
3. कैशिंग (Caching / String Pooling)
जब कंपाइलर हमारे स्ट्रिंग ऑब्जेक्ट्स को ऑप्टिमाइज़ करता है, तो यदि दो ऑब्जेक्ट्स का मान समान होता है (a = "test", और b = "test"), तो हमें केवल एक स्ट्रिंग ऑब्जेक्ट की आवश्यकता होती है (a और b दोनों उसी ऑब्जेक्ट को इंगित करेंगे)। यह स्ट्रिंग पूलिंग/इंटर्निंग केवल इम्यूटेबिलिटी के कारण संभव है।
4. क्लास लोडिंग (Class Loading)
स्ट्रिंग का उपयोग क्लास लोडिंग के लिए आर्गुमेंट्स के रूप में किया जाता है। यदि यह म्यूटेबल होता, तो गलत क्लास लोड हो सकती थी (क्योंकि म्यूटेबल ऑब्जेक्ट्स अपनी स्थिति बदलते हैं)।
5. हैशकोड कैशिंग (HashCode Caching)
चूंकि स्ट्रिंग इम्यूटेबल है, इसका हैशकोड नहीं बदलता। Java स्ट्रिंग का हैशकोड कैश कर लेता है, जिससे यह हैश-आधारित कलेक्शंस (HashMap, HashSet, Hashtable) में कुंजी (key) के रूप में उपयोग के लिए बहुत तेज़ हो जाता है।
उदाहरण: इम्यूटेबिलिटी प्रदर्शन
public class StringImmutableDemo {
public static void main(String[] args) {
String st1 = "Tutorials";
String st2 = "Point";
System.out.println("The hashcode of st1 = " + st1.hashCode());
System.out.println("The hashcode of st2 = " + st2.hashCode());
st1 = st1 + st2; // नया ऑब्जेक्ट बनता है, पुराना अपरिवर्तित रहता है
System.out.println("The Hashcode after st1 is changed: " + st1.hashCode());
}
}
आउटपुट
The hashcode of st1 = -594386763 The hashcode of st2 = 77292912 The Hashcode after st1 is changed: 962735579
व्याख्या
st1 = st1 + st2एक नया स्ट्रिंग ऑब्जेक्ट बनाता है ("TutorialsPoint")।- मूल "Tutorials" ऑब्जेक्ट अपरिवर्तित रहता है (यदि कोई अन्य रेफरेंस नहीं तो GC के लिए पात्र)।
st1अब नए ऑब्जेक्ट को संदर्भित करता है, जिसका हैशकोड अलग है।
क्या होता अगर String म्यूटेबल होता?
// काल्पनिक म्यूटेबल स्ट्रिंग (Java में संभव नहीं)
MutableString ms = new MutableString("Hello");
Map map = new HashMap<>();
map.put(ms, "Value1");
// कहीं और कोड में...
ms.append(" World"); // ms अब "Hello World" है
// map.get(ms) अब काम नहीं करेगा क्योंकि हैशकोड बदल गया!
// HashMap टूट जाएगा।
सारांश
| कारण | लाभ |
|---|---|
| Security | संवेदनशील डेटा (पासवर्ड, URL) टैम्पर-प्रूफ |
| Thread Safety | लॉक के बिना सुरक्षित साझाकरण |
| Caching/Pooling | मेमोरी बचत, तेज़ तुलना |
| Class Loading | सही क्लास लोडिंग गारंटी |
| HashCode Caching | HashMap/HashSet में तेज़ कुंजी ऑपरेशन |
निष्कर्ष: String की इम्यूटेबिलिटी और फाइनल होना Java की सुरक्षा, प्रदर्शन, थ्रेड-सेफ्टी और मेमोरी दक्षता के लिए मौलिक डिजाइन निर्णय है।