【问题标题】:Why doesn't the string change when modifying string array element为什么修改字符串数组元素时字符串不改变
【发布时间】:2019-11-12 05:10:28
【问题描述】:

我无法理解为什么 String 不像对象那样工作,以至于当您更改它时,分配给它的变量也会更改。

我尝试创建一个字符串数组,然后将一个元素的引用分配给一个变量(我说引用是因为据我了解 Java 是按值传递,而内存引用是那个“值”)
当我更改 String 元素时,变量不会反映更改。

String[] arr={"abc","def"};

String s=arr[1];

arr[1]+="123r";

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

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

System.out.println(s); //prints "def"

也许,根据我一直在阅读的内容,赋值运算符不适用于字符串。

【问题讨论】:

  • String 不像对象那样工作,因此当您更改它时,分配给它的 var 也会更改:字符串是对象,并且与任何对象的工作方式完全相同其他对象。 arr[1] +="123r"不会“改变对象”。它等价于 `arr[1] = arr[1] + "123r",即它创建一个新的 String 对象,并将新的 String 对象存储在数组中,索引为 1。
  • 嗯,所以赋值运算符确实没有按预期工作

标签: java arrays oop


【解决方案1】:

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

cmets 中的时间线:

// 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] 的内存地址分配给变量s。 RAM 中的值保持不变,不会改变。

当你这样做时

 arr[1] += "123r";

您正在创建一个全新的字符串。
展开这是一步一步发生的事情。

arr[1] += "123r";
arr[1] = arr[1] + "123r"; 
arr[1] = "def" + "123r";
arr[1] = "def123r";

所以arr[1] 在 =
之后被分配了操作结果的内存地址/引用 但是,此操作与变量 s 完全没有关系,因为该变量保存了原始字符串的地址,并且没有更新该引用/内存地址的代码。

【讨论】:

  • 哦!我明白了,关于不变性的一点很有启发性。感谢您提供有用且详细的评论。
【解决方案2】:

我们知道,java中string是const变量。

  1. String[] arr={"abc","def"}

    常量字符串变量池:"abc", "def"

    arr[0] -> "abc"

    arr[1] -> “定义”

  2. String s=arr[1]

    常量字符串变量池:"abc", "def"

    arr[0] -> "abc"

    arr[1] -> “定义”

    s -> “定义”

  3. arr[1]+="123r"

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

    arr[0] -> "abc"

    arr[1] -> "def123r"

    s -> “定义”

【讨论】:

    【解决方案3】:

    简而言之,您遇到的行为是预期的。在 Java 中,字符串被设计为不可变的,也就是说,它们的值不能改变。

    字符串不变性是什么意思?

    研究下面的代码 sn-p 并尝试在不运行代码的情况下预测输出。

     String s = "Stack";  
     s.concat(" overflow"); 
     System.out.println(s);
    

    您期望输出是什么? 堆栈溢出 对吗?没有!输出是堆栈。你可以自己测试看看。

    这正是字符串的行为方式。

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

     String s = "Stack";  
     s = s.concat(" overflow"); 
     System.out.println(s);
    

    这样就创建了一个新对象,输出变成堆栈溢出

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-09-02
      • 2020-06-02
      • 1970-01-01
      • 2015-10-14
      • 1970-01-01
      • 1970-01-01
      • 2023-03-20
      相关资源
      最近更新 更多