Immutability of Strings in Java

2018-12-31 01:41发布

Consider the following example.

String str = new String();

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

str = "Help!";
System.out.println(str);  //Prints Help!

Now, in Java, String objects are immutable. Then how come the object str can be assigned value "Help!". Isn't this contradicting the immutability of strings in Java? Can anybody please explain me the exact concept of immutability?

Edit:

Ok. I am now getting it, but just one follow-up question. What about the following code:

String str = "Mississippi"; 
System.out.println(str); // prints Mississippi 

str = str.replace("i", "!"); 
System.out.println(str); // prints M!ss!ss!pp! 

Does this mean that two objects are created again ("Mississippi" and "M!ss!ss!pp!") and the reference str points to a different object after replace() method?

24条回答
回忆,回不去的记忆
2楼-- · 2018-12-31 01:54

Though java tries to ignore it, str is nothing more than a pointer. This means that when you first write str = "Hello";, you create an object that str points to. When you reassign str by writing str = "Help!";, a new object is created and the old "Hello" object gets garbage collected whenever java feels like it.

查看更多
呛了眼睛熬了心
3楼-- · 2018-12-31 01:54

Because String is immutable so changes will not occur if you will not assign the returned value of function to the string.so in your question assign value of swap function  returned value to s.

s=swap(s, n1, n2) ;then the value of string s will change.

I was also getting the unchanged value when i was writing the program to get some permutations string(Although it is not giving all the permutations but this is for example to answer your question)

Here is a example.

> import java.io.*;  public class MyString { public static void
> main(String []args)throws IOException {  BufferedReader br=new
> BufferedReader(new InputStreamReader(System.in));  String
> s=br.readLine().trim(); int n=0;int k=0;  while(n!=s.length()) {
> while(k<n){  swap(s,k,n); System.out.println(s); swap(s,k,n); k++; }
> n++; } }  public static void swap(String s,int n1,int n2) { char temp;
> temp=s.charAt(n1); StringBuilder sb=new StringBuilder(s);
> sb.setCharAt(n1,s.charAt(n2)); sb.setCharAt(n2,temp); s=sb.toString();
> } }

but i was not getting the permuted values of the string from above code.So I assigned the returned value of the swap function to the string and got changed values of string. after assigning the returned value i got the permuted values of string.

/import java.util.*; import java.io.*; public class MyString { public static void main(String []args)throws IOException{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); 
String s=br.readLine().trim(); int n=0;int k=0; 
while(n!=s.length()){ while(k<n){ s=swap(s,k,n); 
System.out.println(s); s=swap(s,k,n); k++; } n++; } } 
public static String swap(String s,int n1,int n2){
char temp; temp=s.charAt(n1); StringBuilder sb=new StringBuilder(s); sb.setCharAt(n1,s.charAt(n2)); sb.setCharAt(n2,temp); s=sb.toString(); return s; } }
查看更多
其实,你不懂
4楼-- · 2018-12-31 01:55

Light_handle I recommend you take a read of Cup Size -- a story about variables and Pass-by-Value Please (Cup Size continued). This will help a lot when reading the posts above.

Have you read them? Yes. Good.

String str = new String();

This creates a new "remote control" called "str" and sets that to the value new String() (or "").

e.g. in memory this creates:

str --- > ""

str  = "Hello";

This then changes the remote control "str" but does not modify the original string "".

e.g. in memory this creates:

str -+   ""
     +-> "Hello"

str = "Help!";

This then changes the remote control "str" but does not modify the original string "" or the object that the remote control currently points to.

e.g. in memory this creates:

str -+   ""
     |   "Hello"
     +-> "Help!"
查看更多
妖精总统
5楼-- · 2018-12-31 01:57

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
查看更多
春风洒进眼中
6楼-- · 2018-12-31 01:59

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.

查看更多
十年一品温如言
7楼-- · 2018-12-31 02:01

For those wondering how to break String immutability in Java...

Code

import java.lang.reflect.Field;

public class StringImmutability {
    public static void main(String[] args) {
        String str1 = "I am immutable";
        String str2 = str1;

        try {
            Class str1Class = str1.getClass();
            Field str1Field = str1Class.getDeclaredField("value");

            str1Field.setAccessible(true);
            char[] valueChars = (char[]) str1Field.get(str1);

            valueChars[5] = ' ';
            valueChars[6] = ' ';

            System.out.println(str1 == str2);
            System.out.println(str1);
            System.out.println(str2);           
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }
}

Output

true
I am   mutable
I am   mutable
查看更多
登录 后发表回答