🪨
Strings

String Handling

Immutable Text
💡 String एक पत्थर पर लिखाई जैसा है — एक बार लिखने के बाद बदला नहीं जा सकता, बदलने के लिए नया पत्थर (नया object) बनता है। StringBuilder एक whiteboard है जिसे मिटाकर दोबारा लिख सकते हो।

String immutable है — जब तुम s = s + "x" करते हो, एक नया String object बनता है, पुराना वही रहता है।

अगर बहुत सारे changes करने हैं (जैसे loop में), तो StringBuilder use करो — वो same object को modify करता है, fast होता है।

String s = "Hi";
s = s + " Java";      // new object created

StringBuilder sb = new StringBuilder("Hi");
sb.append(" Java");   // same object modified
🪨
String एक पत्थर पर लिखाई जैसा है — एक बार लिखने के बाद बदला नहीं जा सकता, बदलने के लिए नया पत्थर (नया object) बनता है। StringBuilder एक whiteboard है जिसे मिटाकर दोबारा लिख सकते हो।
1 / 4
⚡ झट से Recap
  • String immutable है
  • Change पर नया object बनता है
  • StringBuilder mutable और fast होता है
इस page में (5 subtopics)

जब तुम String s = "Hi"; लिखते हो (literal), Java पहले "String Pool" (एक special memory area, Heap के अंदर ही) में check करता है कि "Hi" already exist करता है क्या — अगर हाँ, वही reference दे देता है (नया object नहीं बनता, memory बचती है)। यह सिर्फ तभी possible है क्योंकि String immutable है — अगर कोई एक reference से String change कर दे, सब shared references corrupt हो जाते।

लेकिन new String("Hi") *हमेशा* एक नया object Heap में बनाता है, Pool के बाहर — चाहे "Hi" pool में already हो। इसलिए new String() से बनाए Strings को == से compare करना हमेशा risky है।

intern() method call करके तुम किसी भी String को manually Pool में डाल सकते हो (या अगर already है तो उसका pool reference ले सकते हो) — rarely use होता है, लेकिन memory-sensitive applications में useful हो सकता है।

String a = "Hi";
String b = "Hi";
String c = new String("Hi");
System.out.println(a == b);  // true (Pool se same object)
System.out.println(a == c);  // false (c alag object hai)
System.out.println(a.equals(c)); // true (content same hai)
⚠️Common Mistake: String comparison के लिए कभी भी == मत use करो (सिर्फ null check के लिए ठीक है — s == null)। Content compare करना हो तो हमेशा .equals() या .equalsIgnoreCase() use करो।

length() String की लंबाई देता है। charAt(i) specific position का character। substring(start, end) एक हिस्सा निकालता है (end index exclude होता है)। indexOf("x") पहली बार "x" कहाँ मिलता है (नहीं मिलने पर -1)।

contains("x") check करता है substring है या नहीं। replace("a","b") सब occurrences बदल देता है। trim() (या modern strip()) leading/trailing spaces हटाए। split(",") एक array देता है, delimiter के हिसाब से तोड़े हुए।

toUpperCase()/toLowerCase() case बदलते हैं। equalsIgnoreCase() case-insensitive comparison। सब methods नया String return करते हैं (immutability की वजह से), original कभी change नहीं होता।

Methodक्या करता हैExample
length()लंबाई"Java".length() → 4
charAt(i)i-th character"Java".charAt(1) → 'a'
substring(a,b)हिस्सा निकालना"Java".substring(1,3) → "av"
indexOf(x)Position ढूंढना"Java".indexOf('v') → 2
trim()Spaces हटाना" Hi ".trim() → "Hi"
split(x)Array में तोड़ना"a,b".split(",") → ["a","b"]
replace(a,b)Replace करना"Hi".replace('H','B') → "Bi"
String s = "  Hello Java  ";
System.out.println(s.trim());              // "Hello Java"
System.out.println(s.trim().split(" ")[1]); // "Java"
💡Tip: substring(start, end) में "end" index EXCLUDE होता है — "Java".substring(0, 2) सिर्फ "Ja" देता है, "Jav" नहीं। यह एक बहुत common off-by-one confusion है beginners के लिए।

दोनों mutable हैं (same object modify होता है, String की तरह बार-बार नया object नहीं बनता) — append(), insert(), delete(), reverse() जैसी methods देते हैं जो object को in-place modify करती हैं।

फर्क: StringBuffer thread-safe है (methods synchronized हैं, multiple threads एक साथ safely use कर सकते हैं) लेकिन इसलिए थोड़ा slow (synchronization का overhead)। StringBuilder thread-safe नहीं है लेकिन fast है — single-threaded code में (जो ज़्यादा common है) StringBuilder ही recommended है।

Loop में बहुत सारी String concatenation करनी हो, तो StringBuilder use करो — s = s + "x" loop में करने से हर बार एक नया String object बनता है (O(n²) time complexity पूरे loop के लिए), जबकि StringBuilder.append() same object को modify करता है (O(n) total)।

StringStringBuilderStringBuffer
Mutable?नहींहाँहाँ
Thread-safe?हाँ (immutable है इसलिए)नहींहाँ
SpeedSlow (concatenation में)FastMedium
कब use करेंFixed text, thread-safety चाहिएSingle-thread, loops में buildingMulti-thread String building
⚠️Common Mistake: Loop के अंदर String += करना (जैसे for loop में result = result + item;) performance killer है बड़े loops के लिए — हमेशा StringBuilder use करो।

String.format("Name: %s, Age: %d", name, age) से placeholders के साथ clean strings बना सकते हो — %s String के लिए, %d integer, %f decimal (%.2f दो decimal places के साथ)। System.out.printf() same syntax use करता है directly print करने के लिए (format() की तरह, बस return नहीं करता, सीधा print कर देता है)।

String msg = String.format("%s scored %.1f%%", "Aarav", 92.567);
// "Aarav scored 92.6%"
System.out.printf("Total: %d items%n", 5);

String को immutable/final बनाया गया है तीन वजह से: (1) Security — जैसे file paths, network URLs, database credentials String में pass होते हैं; अगर mutable होते तो कोई भी function बीच में secretly बदल सकता था जिससे security holes बन सकते थे।

(2) String Pool सिर्फ immutability की वजह से safely काम कर सकता है — अगर एक reference change कर दे, सब shared references (जो same pooled object point कर रहे हैं) corrupt हो जाते।

(3) Thread-safety free मिलती है बिना extra effort के — immutable objects multiple threads के बीच safely share हो सकते हैं, क्योंकि कोई भी thread इसे change ही नहीं कर सकता। यह String को HashMap keys के लिए भी perfect बनाता है (hashCode कभी change नहीं होता, cache किया जा सकता है — String अपना hashCode internally cache भी करता है performance के लिए)।