Immutability of Strings in Java

后端 未结 26 2374
不思量自难忘°
不思量自难忘° 2020-11-21 06:33

Consider the following example.

String str = new String();

str  = \"Hello\";
System.out.println(str);  //Prints Hello

str = \"Help!\";
System.out.println(s         


        
相关标签:
26条回答
  • 2020-11-21 07:20

    Super late to the answer, but wanted to put a concise message from author of the String class in Java

    Strings are constant; their values cannot be changed after they are created. String buffers support mutable strings. Because String objects are immutable they can be shared.

    It can be derived from this documentation that anything that changes string, returns different object (which could be new or interned and old). The not so subtle hint about this should come from the function signature. Think about it, 'Why did they make a function on an object return an object instead of status?'.

    public String replace(char oldChar, char newChar) 
    

    Also one more source which makes this behaviour explicit (From replace function documentation)

    Returns a new string resulting from replacing all occurrences of oldChar in this string with newChar.

    Source: https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#replace(char,%20char)

    • author Lee Boynton
    • author Arthur van Hoff
    • author Martin Buchholz
    • author Ulf Zibis

    Source: JavaDoc of String.

    0 讨论(0)
  • 2020-11-21 07:21

    Use:

    String s = new String("New String");
    s.concat(" Added String");
    System.out.println("String reference -----> "+s); // Output: String reference -----> New String
    

    If you see here I use the concat method to change the original string, that is, "New String" with a string " Added String", but still I got the output as previous, hence it proves that you can not change the reference of object of String class, but if you do this thing by StringBuilder class it will work. It is listed below.

    StringBuilder sb = new StringBuilder("New String");
    sb.append(" Added String");
    System.out.println("StringBuilder reference -----> "+sb);// Output: StringBuilder reference -----> New String Added String
    
    0 讨论(0)
  • 2020-11-21 07:22

    String is immutable. Which means that we can only change the reference.


    String a = "a";
    System.out.println("String a is referencing to "+a); // Output: a
    
    a.concat("b");
    System.out.println("String a is referencing to "+a); // Output: a
    
    a = a.concat("b");
    System.out.println("String a has created a new reference and is now referencing to "+a); // Output: ab
    
    0 讨论(0)
  • 2020-11-21 07:23

    In Java, objects are generally accessed by references. In your piece of code str is a reference which is first assigned to "Hello" (an automatic created object or fetched from constant pool) and then you assigned another object "Help!" to same reference. A point to note is the reference is the same and modified, but objects are different. One more thing in your code you accessed three objects,

    1. When you called new String().
    2. When you assigned "hello".
    3. When you assigned "help!".

    Calling new String() creates a new object even if it exists in string pool, so generally it should not be used. To put a string created from new String () into string pool you can try the intern() method.

    I hope this helps.

    0 讨论(0)
  • 2020-11-21 07:24

    The string object that was first referenced by str was not altered, all that you did was make str refer to a new string object.

    0 讨论(0)
  • 2020-11-21 07:25

    str is not an object, it's a reference to an object. "Hello" and "Help!" are two distinct String objects. Thus, str points to a string. You can change what it points to, but not that which it points at.

    Take this code, for example:

    String s1 = "Hello";
    String s2 = s1;
    // s1 and s2 now point at the same string - "Hello"
    

    Now, there is nothing1 we could do to s1 that would affect the value of s2. They refer to the same object - the string "Hello" - but that object is immutable and thus cannot be altered.

    If we do something like this:

    s1 = "Help!";
    System.out.println(s2); // still prints "Hello"
    

    Here we see the difference between mutating an object, and changing a reference. s2 still points to the same object as we initially set s1 to point to. Setting s1 to "Help!" only changes the reference, while the String object it originally referred to remains unchanged.

    If strings were mutable, we could do something like this:

    String s1 = "Hello";
    String s2 = s1;
    s1.setCharAt(1, 'a'); // Fictional method that sets character at a given pos in string
    System.out.println(s2); // Prints "Hallo"
    

    Edit to respond to OP's edit:

    If you look at the source code for String.replace(char,char) (also available in src.zip in your JDK installation directory -- a pro tip is to look there whenever you wonder how something really works) you can see that what it does is the following:

    • If there is one or more occurrences of oldChar in the current string, make a copy of the current string where all occurrences of oldChar are replaced with newChar.
    • If the oldChar is not present in the current string, return the current string.

    So yes, "Mississippi".replace('i', '!') creates a new String object. Again, the following holds:

    String s1 = "Mississippi";
    String s2 = s1;
    s1 = s1.replace('i', '!');
    System.out.println(s1); // Prints "M!ss!ss!pp!"
    System.out.println(s2); // Prints "Mississippi"
    System.out.println(s1 == s2); // Prints "false" as s1 and s2 are two different objects
    

    Your homework for now is to see what the above code does if you change s1 = s1.replace('i', '!'); to s1 = s1.replace('Q', '!'); :)


    1 Actually, it is possible to mutate strings (and other immutable objects). It requires reflection and is very, very dangerous and should never ever be used unless you're actually interested in destroying the program.

    0 讨论(0)
提交回复
热议问题