📝 Strings
Strings are objects that represent sequences of characters. In Java, Strings are immutable, widely used, and feature a vast library of built-in methods.
1. String Class in Java
In Java, a String is an object, not a primitive type, representing a sequence of characters. It is part of the java.lang package and implements interfaces like Serializable, Comparable, and CharSequence.
2. String Immutability
Once a String object is created, its data or state cannot be changed. If you try to modify a string, a new String object is created behind the scenes. This is called immutability.
Why are Strings immutable?
- Caching (String Pool): Allows literal sharing, saving memory.
- Thread safety: Immutable objects cannot be altered, making them inherently thread-safe.
- Security: Used extensively for class loading, network connections, file paths.
- Performance: Hash codes are cached, making String excellent for HashMap keys.
Memory Diagram:
String s1 = "Hello";
// s1 points to "Hello" in String Pool
s1 = s1 + " World";
// A NEW string "Hello World" is created in memory.
// s1 now points to "Hello World". "Hello" remains unchanged in the pool.
3. String Creation & String Pool
Strings can be created in two ways:
- String Literal:
String s = "Java";
JVM checks the String Constant Pool. If "Java" exists, a reference to the pooled instance is returned. Otherwise, a new instance is created in the pool. - New Keyword:
String s = new String("Java");
This forces the creation of a new String object in Heap memory, bypassing the pool entirely.
public class StringPoolDemo { public static void main(String[] args) { String s1 = "Java"; String s2 = "Java"; String s3 = new String("Java"); // == compares memory references System.out.println("s1 == s2 : " + (s1 == s2)); // true (same pool object) System.out.println("s1 == s3 : " + (s1 == s3)); // false (s3 is in heap) // .equals() compares actual content System.out.println("s1.equals(s3) : " + s1.equals(s3)); // true } }
4. Important String Methods
public class StringMethodsDemo { public static void main(String[] args) { String text = " Java Programming "; System.out.println("length(): " + text.length()); System.out.println("trim(): '" + text.trim() + "'"); System.out.println("strip(): '" + text.strip() + "'"); // Java 11+ String clean = text.trim(); System.out.println("charAt(0): " + clean.charAt(0)); System.out.println("substring(0,4): " + clean.substring(0, 4)); System.out.println("indexOf('a'): " + clean.indexOf("a")); System.out.println("lastIndexOf('a'): " + clean.lastIndexOf("a")); System.out.println("contains(\"Pro\"): " + clean.contains("Pro")); System.out.println("replace(): " + clean.replace("Java", "Python")); System.out.println("toUpperCase(): " + clean.toUpperCase()); System.out.println("isEmpty(): " + "".isEmpty()); System.out.println("isBlank(): " + " ".isBlank()); // Java 11+ // Split String[] words = clean.split(" "); System.out.println("Words: " + words.length); // Join (Java 8+) System.out.println("join(): " + String.join("-", words)); } }
5. StringBuilder and StringBuffer
Because Strings are immutable, concatenating strings in a loop creates many temporary objects, wasting memory and CPU time. To solve this, Java provides two mutable string classes:
| Feature | String | StringBuilder | StringBuffer |
|---|---|---|---|
| Mutability | Immutable | Mutable | Mutable |
| Thread Safety | Safe (immutable) | Not Safe (fast) | Safe (synchronized, slower) |
| Performance | Slowest for modifications | Fastest | Slower than StringBuilder |
public class StringBuilderDemo { public static void main(String[] args) { StringBuilder sb = new StringBuilder("Hello"); sb.append(" World"); sb.insert(5, ","); System.out.println(sb.toString()); // Hello, World sb.delete(5, 6); System.out.println(sb.toString()); // Hello World sb.reverse(); System.out.println(sb.toString()); // dlroW olleH } }