[java] String is immutable. What exactly is the meaning?

I wrote the following code on immutable Strings.

public class ImmutableStrings {

    public static void main(String[] args) {
        testmethod();
    }

    private static void testmethod() {
        String a = "a";
        System.out.println("a 1-->" + a);
        a = "ty";
        System.out.println("a 2-->" + a);
    }
}

Output:

a 1-->a  
a 2-->ty

Here the value of variable a has been changed (while many say that contents of the immutable objects cannot be changed). But what exactly does one mean by saying String is immutable? Could you please clarify this topic for me?

source : https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html

This question is related to java string immutability

The answer is


Java String is immutable, String will Store the value in the form of object. so if u assign the value String a="a"; it will create an object and the value is stored in that and again if you are assigning value a="ty" means it will create an another object store the value in that, if you want to understand clearly, check the has code for the String.


Probably every answer provided above is right, but my answer is specific to use of hashCode() method, to prove the points like, String... once created can't be modified and modifications will results in new value at different memory location.

public class ImmutabilityTest {

    private String changingRef = "TEST_STRING";

    public static void main(String a[]) {

        ImmutabilityTest dn = new ImmutabilityTest();

        System.out.println("ChangingRef for TEST_STRING OLD : "
                + dn.changingRef.hashCode());

        dn.changingRef = "NEW_TEST_STRING";
        System.out.println("ChangingRef for NEW_TEST_STRING : "
                + dn.changingRef.hashCode());

        dn.changingRef = "TEST_STRING";
        System.out.println("ChangingRef for TEST_STRING BACK : "
                + dn.changingRef.hashCode());

        dn.changingRef = "NEW_TEST_STRING";
        System.out.println("ChangingRef for NEW_TEST_STRING BACK : "
                + dn.changingRef.hashCode());

        String str = new String("STRING1");
        System.out.println("String Class STRING1 : " + str.hashCode());

        str = new String("STRING2");
        System.out.println("String Class STRING2 : " + str.hashCode());

        str = new String("STRING1");
        System.out.println("String Class STRING1 BACK : " + str.hashCode());

        str = new String("STRING2");
        System.out.println("String Class STRING2 BACK : " + str.hashCode());

    }
}

OUTPUT

ChangingRef for TEST_STRING OLD : 247540830
ChangingRef for NEW_TEST_STRING : 970356767
ChangingRef for TEST_STRING BACK : 247540830
ChangingRef for NEW_TEST_STRING BACK : 970356767
String Class STRING1 : -1163776448
String Class STRING2 : -1163776447
String Class STRING1 BACK : -1163776448
String Class STRING2 BACK : -1163776447

In your example, a refers first to "a", and then to "ty". You're not mutating any String instance; you're just changing which String instance a refers to. For example, this:

String a = "a";
String b = a; // b refers to the same String as a
a = "b"; // a now refers to a different instance
System.out.println(b);

prints "a", because we never mutate the String instance that b points to.


Only the reference is changing. First a was referencing to the string "a", and later you changed it to "ty". The string "a" remains the same.


String S1="abc";
S1.concat("xyz");
System.out.println("S1 is", + S1);
String S2=S1.concat("def");
System.out.println("S2 is", + S2);

This shows that once a string object is create it cannot be changed. EveryTime you need to create new and put in another String. S


String is immutable means that you cannot change the object itself, but you can change the reference to the object.

When you execute a = "ty", you are actually changing the reference of a to a new object created by the String literal "ty".

Changing an object means to use its methods to change one of its fields (or the fields are public and not final, so that they can be updated from outside without accessing them via methods), for example:

Foo x = new Foo("the field");
x.setField("a new field");
System.out.println(x.getField()); // prints "a new field"

While in an immutable class (declared as final, to prevent modification via inheritance)(its methods cannot modify its fields, and also the fields are always private and recommended to be final), for example String, you cannot change the current String but you can return a new String, i.e:

String s = "some text";
s.substring(0,4);
System.out.println(s); // still printing "some text"
String a = s.substring(0,4);
System.out.println(a); // prints "some"

In your example, the variable a is just a reference to an instance of a string object. When you say a = "ty", you are not actually changing the string object, but rather pointing the reference at an entirely different instance of the string class.


You're changing what a refers to. Try this:

String a="a";
System.out.println("a 1-->"+a);
String b=a;
a="ty";
System.out.println("a 2-->"+a);
System.out.println("b  -->"+b);

You will see that the object to which a and then b refers has not changed.

If you want to prevent your code from changing which object a refers to, try:

final String a="a";

see here

class ImmutableStrings {

    public static void main(String[] args) {
        testmethod();
    }

    private static void testmethod() {
    String a="a";
    System.out.println("a 1-->"+a);
    System.out.println("a 1 address-->"+a.hashCode());

    a = "ty";
    System.out.println("a 2-->"+a);

       System.out.println("a 2 address-->"+a.hashCode());
    }
}

output:

a 1-->a
a 1 address-->97
a 2-->ty
a 2 address-->3717

This indicates that whenever you are modifying the content of immutable string object a a new object will be created. i.e you are not allowed to change the content of immutable object. that's why the address are different for both the object.


A string is a char[] containing a series of UTF-16 code units, an int offset into that array, and an int length.

For example.

String s

It creates space for a string reference. Assigning copies references around but does not modify the objects to which those references refer.

You should also be aware that

new String(s)

doesn't really do anything useful. It merely creates another instance backed by the same array, offset, and length as s. There is very rarely a reason to do this so it is considered bad practice by most Java programmers.

Java double quoted strings like "my string" are really references to interned String instances so "bar" is a reference to the same String instance regardless of how many times it appears in your code.


The "hello" creates one instance that is pooled, and the new String(...) creates a non-pooled instance. Try System.out.println(("hello" == "hello") + "," + (new String("hello") == "hello") + "," + (new String("hello") == new String("hello"))); and you should see true,false,false


I think the following code clears the difference:

String A = new String("Venugopal");
String B = A;

A = A +"mitul";

System.out.println("A is " + A);
System.out.println("B is " + B);

StringBuffer SA = new StringBuffer("Venugopal");
StringBuffer SB = SA;

SA = SA.append("mitul");

System.out.println("SA is " + SA);
System.out.println("SB is " + SB);

immutable means you can't not change the value of the same referance.every time you required to create new referance means new memory location. ex:

String str="abc";
str="bcd";

here, in the above code ,in the memory there are 2 blocks for storing the value.the first for value "abc" and second for "bcd".the second value is not replace to first value.

this is call the immutable.


You are not changing the object in the assignment statement, you replace one immutable object with another one. Object String("a") does not change to String("ty"), it gets discarded, and a reference to ty gets written into a in its stead.

In contrast, StringBuffer represents a mutable object. You can do this:

StringBuffer b = new StringBuffer("Hello");
System.out.writeln(b);
b.append(", world!");
System.out.writeln(b);

Here, you did not re-assign b: it still points to the same object, but the content of that object has changed.


You are actually getting a reference to a new string, the string itself is not being changed as it is immutable. This is relevant.

See

Immutable objects on Wikipedia


An immutable object is an object whose state cannot be modified after it is created.

So a = "ABC" <-- immutable object. "a" holds reference to the object. And, a = "DEF" <-- another immutable object, "a" holds reference to it now.

Once you assign a string object, that object can not be changed in memory.

In summary, what you did is to change the reference of "a" to a new string object.


Hope the below code would clarify your doubts :

public static void testString() {
    String str = "Hello";
    System.out.println("Before String Concat: "+str);
    str.concat("World");
    System.out.println("After String Concat: "+str);
    StringBuffer sb = new StringBuffer("Hello");
    System.out.println("Before StringBuffer Append: "+sb);
    sb.append("World");
    System.out.println("After StringBuffer Append: "+sb);
}

Before String Concat: Hello
After String Concat: Hello
Before StringBuffer Append: Hello
After StringBuffer Append: HelloWorld


String is immutable it means that,the content of the String Object can't be change, once it is created. If you want to modify the content then you can go for StringBuffer/StringBuilder instead of String. StringBuffer and StringBuilder are mutable classes.


If some object bar holds a reference to a mutable object foo and encapsulates some of its state in mutable aspects of foo's state, that will allow code which can change those aspects of foo to change the corresponding aspects of bar's state without actually touching bar or even knowing of its existence. Generally, this means that objects which encapsulate their own state using mutable objects must ensure that no references to those objects are exposed to any code which might unexpectedly mutate them. By contrast, if bar holds a reference to an object moo and only uses immutable aspects of moo other than identity to encapsulate its state, then bar can freely expose moo to outside code without worrying about anything the outside code might do to it.


Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to string

How to split a string in two and store it in a field String method cannot be found in a main class method Kotlin - How to correctly concatenate a String Replacing a character from a certain index Remove quotes from String in Python Detect whether a Python string is a number or a letter How does String substring work in Swift How does String.Index work in Swift swift 3.0 Data to String? How to parse JSON string in Typescript

Examples related to immutability

Enums in Javascript with ES6 Correct way to push into state array What is difference between mutable and immutable String in java Const in JavaScript: when to use it and is it necessary? Aren't Python strings immutable? Then why does a + " " + b work? String is immutable. What exactly is the meaning? Immutable vs Mutable types Java Immutable Collections Set System.Drawing.Color values Remove specific characters from a string in Python