String is immutable. What exactly is the meaning? [duplicate]
Asked Answered
T

19

229

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

Torray answered 10/1, 2012 at 4:4 Comment(3)
immutable in the sense of memory. It creates new objects every time you create strings or assign a new string/change the value. That's why it is advisable to be careful when using strings. Charbuffer would be better.Noisette
#93591. Take a look at this for better explanation.Noisette
String is immutable ( once created can not be changed ) object . The object created as a String is stored in the Constant String Pool. Every immutable object in Java is thread safe ,that implies String is also thread safe . String can not be used by two threads simultaneously. String once assigned can not be changed.Raskind
K
472

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.

Korman answered 30/7, 2013 at 8:45 Comment(5)
"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." AND "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." Good explanation!Anaesthesiology
This changed my life :- "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."Echolocation
@Korman Excellent, can you add String a = new String("a"); immutable concepts as well.Hurwit
String s1 = "hello"; String s2 = "world"; String s3 = s1+s2; String s4 = "helloworld"; System.out.println(s3 == s4); here why it is showing false?Mouthy
What an answer ! - This was the key statement - "An important point to note here is that, while the String object is immutable, its reference variable is not". Thanks a lot!Captainship
I
177

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"
Isentropic answered 10/1, 2012 at 4:7 Comment(1)
your example with String was very much required. ThanksSedimentology
E
19

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";
Evangelinaevangeline answered 10/1, 2012 at 4:7 Comment(6)
String a=new String("a"); Now, I have created object 'a'. If I try to modify the value in this object a, it wont be possible ?Torray
That's true. String a = "a"; means essentially the same thing as String a = new String("a"); in Java (except for string interning).Evangelinaevangeline
One last doubt. Now I understood that I was changeing the reference, and this is allowed. What exactly is not allowed, when we say String is immutable? Changing the contents of the object !!! Can you give example of this ?? I mean what cannot be done with stringTorray
The String class is immutable because it has no methods that can change its contents. Contrast this with StringBuilder, which has methods such as .append() and .delete(), and is not immutable.Evangelinaevangeline
@Ajj see my answer for the example you are looking for :)Isentropic
I believe you can change the value of String using reflection. In the sense that they are not truly immutable. Not entirely sure though.Noisette
S
5

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

Scow answered 10/1, 2012 at 4:11 Comment(0)
M
4

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.

Maricruzmaridel answered 10/1, 2012 at 4:19 Comment(1)
This doesn't answer OP because immutability has to do with modification of a String value. But here you simply showing two different string literals and assigning to same reference.Gelatinoid
N
3

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.

Neisa answered 10/1, 2012 at 4:8 Comment(0)
D
3

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.

Duralumin answered 29/9, 2014 at 11:25 Comment(1)
a = "ty"; is the new object in heap. right? what will happen to String a ="a"; ?Crump
S
2

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.

Stines answered 10/1, 2012 at 4:7 Comment(0)
S
2

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

Soissons answered 10/1, 2012 at 4:7 Comment(0)
S
2

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.

Simulant answered 10/1, 2012 at 4:18 Comment(0)
S
2
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

Sodality answered 13/9, 2013 at 6:31 Comment(0)
P
2

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);
Pascoe answered 14/11, 2013 at 18:5 Comment(0)
S
2

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.

Senhorita answered 18/4, 2014 at 6:46 Comment(0)
N
1

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.

Nadya answered 10/1, 2012 at 4:8 Comment(0)
H
1

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.

Herbivorous answered 10/1, 2012 at 4:8 Comment(0)
F
1

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.

Fink answered 2/7, 2013 at 15:9 Comment(0)
L
1

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

Locomotion answered 24/3, 2014 at 6:54 Comment(2)
It would have been better if you added some explanation to it rather than just writing some codeVervain
I can see what he tries to do here, Showing the String 'str' is not changing (or should i said Adding) to HelloWorld. but when you using the StringBuffer it does change. anyway, it's just show that Strings are Immutables.Scyros
D
1

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.

Durkheim answered 3/7, 2014 at 10:2 Comment(0)
H
1

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
Helio answered 1/1, 2015 at 17:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.