String is immutable. What exactly is the meaning?

JavaStringImmutability

Java Problem Overview


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

Java Solutions


Solution 1 - Java

Before proceeding further with the fuss of immutability, let's just take a look into the String class and its functionality a little before coming to any conclusion.

This is how String works:

String str = "knowledge";

This, as usual, creates a string containing "knowledge" and assigns it a reference str. Simple enough? Lets perform some more functions:

 String s = str;     // assigns a new reference to the same string "knowledge"

Lets see how the below statement works:

  str = str.concat(" base");

This appends a string " base" to str. But wait, how is this possible, since String objects are immutable? Well to your surprise, it is.

When the above statement is executed, the VM takes the value of String str, i.e. "knowledge" and appends " base", giving us the value "knowledge base". Now, since Strings are immutable, the VM can't assign this value to str, so it creates a new String object, gives it a value "knowledge base", and gives it a reference str.

An important point to note here is that, while the String object is immutable, its reference variable is not. So that's why, in the above example, the reference was made to refer to a newly formed String object.

At this point in the example above, we have two String objects: the first one we created with value "knowledge", pointed to by s, and the second one "knowledge base", pointed to by str. But, technically, we have three String objects, the third one being the literal "base" in the concat statement.

Important Facts about String and Memory usage

What if we didn't have another reference s to "knowledge"? We would have lost that String. However, it still would have existed, but would be considered lost due to having no references. Look at one more example below

String s1 = "java";
s1.concat(" rules");
System.out.println("s1 refers to "+s1);  // Yes, s1 still refers to "java"

What's happening:

  1. The first line is pretty straightforward: create a new String "java" and refer s1 to it.
  2. Next, the VM creates another new String "java rules", but nothing refers to it. So, the second String is instantly lost. We can't reach it.

The reference variable s1 still refers to the original String "java".

Almost every method, applied to a String object in order to modify it, creates new String object. So, where do these String objects go? Well, these exist in memory, and one of the key goals of any programming language is to make efficient use of memory.

As applications grow, it's very common for String literals to occupy large area of memory, which can even cause redundancy. So, in order to make Java more efficient, the JVM sets aside a special area of memory called the "String constant pool".

When the compiler sees a String literal, it looks for the String in the pool. If a match is found, the reference to the new literal is directed to the existing String and no new String object is created. The existing String simply has one more reference. Here comes the point of making String objects immutable:

In the String constant pool, a String object is likely to have one or many references. If several references point to same String without even knowing it, it would be bad if one of the references modified that String value. That's why String objects are immutable.

Well, now you could say, what if someone overrides the functionality of String class? That's the reason that the String class is marked final so that nobody can override the behavior of its methods.

Solution 2 - Java

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"

Solution 3 - Java

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";

Solution 4 - Java

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

Solution 5 - Java

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.

Solution 6 - Java

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.

Solution 7 - Java

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.

Solution 8 - Java

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.

Solution 9 - Java

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

Solution 10 - Java

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.

Solution 11 - Java

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

Solution 12 - Java

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);

Solution 13 - Java

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.

Solution 14 - Java

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.

Solution 15 - Java

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.

Solution 16 - Java

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.

Solution 17 - Java

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

Solution 18 - Java

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.

Solution 19 - Java

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAnuj BalanView Question on Stackoverflow
Solution 1 - Javaroger_thatView Answer on Stackoverflow
Solution 2 - JavaEng.FouadView Answer on Stackoverflow
Solution 3 - JavaGreg HewgillView Answer on Stackoverflow
Solution 4 - JavaLionView Answer on Stackoverflow
Solution 5 - JavaRakesh PatelView Answer on Stackoverflow
Solution 6 - JavaJon NewmuisView Answer on Stackoverflow
Solution 7 - JavaRustamView Answer on Stackoverflow
Solution 8 - JavaSergey KalinichenkoView Answer on Stackoverflow
Solution 9 - JavaJordanView Answer on Stackoverflow
Solution 10 - JavaAntoineDeSaintExuperyView Answer on Stackoverflow
Solution 11 - JavaSuryaView Answer on Stackoverflow
Solution 12 - JavaAnkit SinhaView Answer on Stackoverflow
Solution 13 - JavaSelvaView Answer on Stackoverflow
Solution 14 - JavaBhesh GurungView Answer on Stackoverflow
Solution 15 - JavaruakhView Answer on Stackoverflow
Solution 16 - JavasupercatView Answer on Stackoverflow
Solution 17 - JavatechnolishaView Answer on Stackoverflow
Solution 18 - Javauser095736View Answer on Stackoverflow
Solution 19 - JavaPrabhukumar DevarajView Answer on Stackoverflow