Fundamentals 9 min read

What Is an Immutable Object in Java? Understanding String Immutability

This article explains the concept of immutable objects in Java, using String as a case study, clarifies the difference between object references and objects, examines String’s internal fields across JDK versions, demonstrates how typical mutating methods actually create new instances, and shows how reflection can bypass immutability.

Java Captain
Java Captain
Java Captain
What Is an Immutable Object in Java? Understanding String Immutability

In Java, an immutable object is one whose state cannot be changed after it is created; none of its fields, whether primitive or reference types, can be modified.

The confusion often arises from mixing up the object itself with the reference that points to it. For example:

String s = "ABCabc";
System.out.println("s = " + s);

s = "123456";
System.out.println("s = " + s);

The output shows the reference s changing, but the original String objects remain unchanged in memory.

String’s immutability stems from its internal fields. In JDK 6 the class contains:

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
    private final char value[];
    private final int offset;
    private final int count;
    private int hash; // default 0
}

In JDK 7 the layout is simplified to:

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
    private final char value[];
    private int hash; // default 0
}

All these fields are private and final, so external code cannot modify them. Methods such as replace, substring, or toLowerCase appear to change a string, but they actually create and return a new String instance:

String a = "ABCabc";
System.out.println("a = " + a);

a = a.replace('A', 'a');
System.out.println("a = " + a);

Output: a = ABCabc<br/>a = aBCabc When the result is ignored, the original string stays the same:

String ss = "123456";
System.out.println("ss = " + ss);

ss.replace('1', '0');
System.out.println("ss = " + ss);

Output: ss = 123456<br/>ss = 123456 Using reflection, however, one can bypass the final restriction and modify the internal char[] of a String:

public static void testReflection() throws Exception {
    String s = "Hello World";
    System.out.println("s = " + s); // Hello World

    Field valueField = String.class.getDeclaredField("value");
    valueField.setAccessible(true);
    char[] value = (char[]) valueField.get(s);
    value[5] = '_';
    System.out.println("s = " + s); // Hello_World
}

Output: s = Hello World<br/>s = Hello_World This demonstrates that while Java’s String class is designed to be immutable, advanced techniques like reflection can alter its internal state, and immutability also depends on the immutability of any composed objects.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

ReflectionStringprogramming fundamentalsreferenceImmutable Object
Java Captain
Written by

Java Captain

Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.