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.
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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
