考虑下面的例子。

String str = new String();

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

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

在Java中,String对象是不可变的。那么为什么对象str可以被赋值为"Help!"呢?这难道不是与Java中字符串的不变性相矛盾吗?有人能给我解释一下不变性的确切概念吗?

编辑:

好的。我现在明白了,但还有一个问题。下面的代码呢:

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

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

这是否意味着将再次创建两个对象(“Mississippi”和“M!ss!ss!pp!”),并且在replace()方法之后引用str指向不同的对象?


当前回答

Object字符串-方法本身是“不可变的”。 此操作不会产生任何更改:“字母”。替换(“bbb”、“aaa”);“

但是分配数据会导致Strings内容的改变:

    letters = "aaa";
    letters=null;
    System.out.println(letters);
    System.out.println(oB.hashCode());
    System.out.println(letters);
    letters = "bbbaaa";
    System.out.println(oB.hashCode());
    System.out.println(letters);

// string Object的hashcode不变。

其他回答

超级晚的答案,但想把一个简洁的消息从作者的String类在Java

字符串是常量;它们的值在被修改之后就不能再修改了 创建。字符串缓冲区支持可变字符串。因为字符串 对象是不可变的,它们可以被共享。

它可以从这个文档中导出,任何改变字符串的东西,都会返回不同的对象(可以是新的或旧的)。 关于这一点不那么微妙的提示应该来自函数签名。 想想看,为什么他们让一个对象上的函数返回一个对象而不是状态?

public String replace(char oldChar, char newChar) 

还有一个来源使这种行为显式(从替换函数文档)

返回一个新字符串,该字符串由替换所有出现的 oldChar和newChar。

来源:https://docs.oracle.com/javase/7/docs/api/java/lang/String.html取代(char、% 20字符)

作者李·博因顿 作者阿瑟·范霍夫 作者马丁·布赫兹 作者乌尔夫·齐比斯

来源:JavaDoc of String。

我建议你读一读《Cup Size》——一个关于变量和值传递的故事(续《Cup Size》)。这对阅读上面的文章有很大帮助。

你读过吗?是的。好。

String str = new String();

这将创建一个名为“str”的新“远程控制”,并将其设置为值new String()(或“”)。

例如,在内存中创建:

str --- > ""

str  = "Hello";

这将更改远程控制“str”,但不会修改原始字符串“”。

例如,在内存中创建:

str -+   ""
     +-> "Hello"

str = "Help!";

这将更改远程控件“str”,但不会修改原始字符串“”或远程控件当前指向的对象。

例如,在内存中创建:

str -+   ""
     |   "Hello"
     +-> "Help!"

因为String是不可变的,所以如果你不把function的返回值赋给String,就不会发生变化。所以在你的问题中,将swap函数的返回值赋给s。

S =swap(S, n1, n2);那么字符串S的值将会改变。

我也得到了不变的值,当我写程序得到一些排列字符串(虽然它没有给出所有的排列,但这是为了回答你的问题)

这里有一个例子。

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

但是我没有从上面的代码得到字符串的排列值。因此,我将swap函数的返回值分配给字符串,并得到了更改的字符串值。在分配返回值后,我得到了字符串的排列值。

/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; } }

关于你问题的替换部分,试试这个:

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

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

字符串是不可变的。这意味着我们只能改变引用。


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