Java 为什么';t当修改字符串数组元素时,字符串将发生更改

Java 为什么';t当修改字符串数组元素时,字符串将发生更改,java,arrays,oop,Java,Arrays,Oop,我无法理解为什么字符串不能像对象一样工作,以至于当您更改它时,它所分配给的变量也会更改 我尝试过创建一个字符串数组,然后将一个元素的引用分配给一个变量(我说reference,因为据我所知,Java是按值传递的,内存引用就是那个“值”) 当我更改字符串元素时,变量没有反映更改 String[]arr={“abc”,“def”}; 字符串s=arr[1]; arr[1]+=“123r”; 对于(字符串i:arr){System.out.print(i);} System.out.println()

我无法理解为什么字符串不能像对象一样工作,以至于当您更改它时,它所分配给的变量也会更改

我尝试过创建一个字符串数组,然后将一个元素的引用分配给一个变量(我说reference,因为据我所知,Java是按值传递的,内存引用就是那个“值”)
当我更改字符串元素时,变量没有反映更改

String[]arr={“abc”,“def”};
字符串s=arr[1];
arr[1]+=“123r”;
对于(字符串i:arr){System.out.print(i);}
System.out.println();//打印“abcdef123r”
系统输出打印项次//打印“def”

也许,从我所读到的内容来看,赋值运算符对字符串的作用不是那样的。

字符串是不可变的。这意味着它们的价值永远不会改变。他们的引用可以被重新分配,这就是这里发生的事情

评论中的时间线:

// Create two Strings. [string1]="abc", [string2]="def"
// Assign [string1] to arr[0]. 
// Assign [string2] to arr[1].
String[] arr={"abc","def"};

// Get value from arr[1] = [string2]
// Assign [string2] to s
String s=arr[1];

// Get value from arr[1] = [string2]
// create [string3] = "123r"
// create [string4] = [string2] + [string3]
// assign [string4] to arr[1]
arr[1]+="123r";

// get value from arr[0] = [string1]
// print [string1] = "abc"
// get value from arr[1] = [string4]
// print [string4] = "def123r"

for (String i:arr) {System.out.print(i);}

System.out.println(); // prints "abcdef123r"

// get value from s = [string2]
// print value "def"
System.out.println(s); //prints "def"
我之所以说引用,是因为据我所知,Java是按值传递的,而内存引用就是那个“值”

几乎正确。
引用是一个地址。该值可在该地址的内存中找到

因此,您拥有的是:
变量=人类可读。苹果。
参考=内存地址。计算机可读。
value=给定地址的内存中的一些字节

所以当你这么做的时候

 String s = arr[1];
 arr[1] += "123r";
您正在将链接到变量
arr[1]
的内存地址分配给变量
s
。RAM中的值是不变的,不会改变

当你这样做的时候

 String s = arr[1];
 arr[1] += "123r";
您正在创建一个全新的字符串。
这是一步一步发生的事情

arr[1] += "123r";
arr[1] = arr[1] + "123r"; 
arr[1] = "def" + "123r";
arr[1] = "def123r";
因此,
arr[1]
在=

但是,此操作与变量
s
没有任何关系,因为此变量保存原始字符串的地址,并且没有代码更新该引用/内存地址。

我们知道,字符串在java中是常量变量

  • String[]arr={“abc”,“def”}

    常量字符串变量池:“abc”、“def”

    arr[0]->“abc”

    arr[1]->“def”

  • String s=arr[1]

    常量字符串变量池:“abc”、“def”

    arr[0]->“abc”

    arr[1]->“def”

    s->“def”

  • arr[1]+=“123r”

    常量字符串变量池:“abc”、“def”、“def123r”、“123r”

    arr[0]->“abc”

    arr[1]->“def123r”

    s->“def”


  • 简而言之,你所经历的行为是预期的。在Java中,字符串被设计为不可变的,也就是说,它们的值不能更改

    字符串不变性意味着什么?

    研究下面的代码片段,并尝试在不运行代码的情况下预测输出

     String s = "Stack";  
     s.concat(" overflow"); 
     System.out.println(s);
    
    您希望输出是什么?堆栈溢出,对吗?不!输出为堆栈。您可以自己测试和查看

    这正是字符串的行为方式

    当然,通过这样做,我们可以修改上面的代码库,使其以我们想要的方式工作:

     String s = "Stack";  
     s = s.concat(" overflow"); 
     System.out.println(s);
    
    这样,将创建一个新对象,输出将变为堆栈溢出

    我希望这有帮助。快乐的编码!
    已编辑的

    字符串的工作方式与对象不同,因此当您更改它时,分配给它的变量也会更改:字符串是对象,其工作方式与任何其他对象完全相同<代码>arr[1]+=“123r”不“更改对象”。它相当于'arr[1]=arr[1]+“123r”,即它创建了一个新的字符串对象,并将该新字符串对象存储在数组中的索引1.Hmm处,因此赋值运算符确实不能按预期工作!我明白了,关于不变性的一点很有启发性。谢谢你的帮助和详细的评论。