Java.Core.Why is String an immutable and finalizable class?

Why is String Immutable and Final in Java?

The String class in Java is immutable (cannot be modified) and final (cannot be subclassed). This design choice was made for security, performance, and thread safety reasons.


1. Security

If String were mutable, it could be changed unintentionally or maliciously, leading to security vulnerabilities.

Example:

public class SecurityExample {
    public static void main(String[] args) {
        String password = "mySecret";
        // If String were mutable, a malicious function could change its value!
        authenticate(password);
        System.out.println(password); // Still "mySecret", ensuring security
    }

    static void authenticate(String password) {
        // If String were mutable, an attacker could modify `password`
    }
}

🛑 Problem if String were mutable: A hacker could modify password while being processed.
Solution: Since String is immutable, it remains unchanged, ensuring safe authentication.

Security Example: Preventing URL Tampering

String url = "https://secure-site.com/login";
connectToServer(url);

If url were mutable, a malicious program could change "secure-site.com" to "fake-site.com".

2. Memory Optimization (String Pool)

Since String is immutable, Java reuses strings efficiently using the String Pool.

Example:

String s1 = "Hello";
String s2 = "Hello"; // Same reference as s1
System.out.println(s1 == s2); // true

Benefit: Java reuses existing string literals, reducing memory consumption.

If String were mutable, two references (s1 and s2) could point to the same object, leading to unexpected changes.


3. Thread Safety

Since String objects cannot be modified, they are inherently thread-safe.

Example:

class SharedResource {
    static String message = "Hello";
}

public class ThreadSafetyExample {
    public static void main(String[] args) {
        new Thread(() -> System.out.println(SharedResource.message)).start();
        new Thread(() -> System.out.println(SharedResource.message)).start();
    }
}

Benefit: No need for synchronization—multiple threads can safely share a String object.

If String were mutable, one thread could change it while another is reading, causing race conditions.


4. HashCode Caching for Performance

  • Since String is immutable, its hash code is computed only once and cached.
  • This improves performance when using String in hash-based collections (HashMap, HashSet).

Example:

public class HashCodeExample {
    public static void main(String[] args) {
        String s = "Java";
        System.out.println(s.hashCode()); // Computed once and cached
        System.out.println(s.hashCode()); // Fast lookup
    }
}

Benefit: HashMap lookups are faster because the hash code does not change.

If String were mutable, the hash code could change, making it unusable in hash-based collections.

5. Preventing Unintended Changes

If String were mutable, a single modification could affect multiple references.

Example:

String s1 = "Java";
String s2 = s1; // s1 and s2 point to the same object

s1 = s1 + " Rocks!"; // Creates a new object, s2 remains unchanged

System.out.println(s1); // Java Rocks!
System.out.println(s2); // Java

Benefit: Modifications create new objects, preventing accidental changes.

If String were mutable, modifying s1 would also modify s2, leading to unpredictable behavior.


6. final Prevents Subclassing

The final keyword prevents inheritance of the String class.

public final class String {
    // Implementation
}

Why?

  • Prevents overriding methods that could break immutability.
  • Protects security-sensitive operations (e.g., hashing, pooling).

If String were not final, malicious subclasses could modify its behavior.


Key Takeaways

ReasonBenefit
SecurityPrevents modification of sensitive data (e.g., passwords, URLs).
Memory EfficiencyEnables String Pooling (string reuse, less memory).
Thread SafetyNo need for synchronization—safe for multithreading.
Performance BoostHash code is cached, making hash-based collections faster.
PredictabilityPrevents unintended modifications when passing strings around.
Prevent Subclassing (final)Ensures immutability and prevents security risks.

Conclusion

Java String is immutable to ensure security, performance, and thread safety.
Being final prevents modification through subclassing.
This makes Java’s string handling highly efficient and reliable.

This entry was posted in Без рубрики. Bookmark the permalink.