【问题标题】:How can I change the the string contents in String array using enhanced-for loops?如何使用增强的for循环更改字符串数组中的字符串内容?
【发布时间】:2021-06-10 11:26:17
【问题描述】:

我是 Java 初学者,我对增强的 for 循环和字符串数组有一些疑问。 在下面的源代码中,我一直在尝试使用增强的 for 循环来更改数组的内容。 似乎我无法更改字符串数组(arrString)中的内容,但我不知道具体原因。 (它适用于 StringBuilder 对象。) 我有点困惑,因为我实际上可以在正常情况下执行 str1+=str2 之类的操作并更改字符串内容(尽管此操作是通过 StringBuilder 类完成的)。

谁能指出为什么会发生这种情况以及我是否有任何误解?

class EnhancedForTest{
    public static void main(String[] args){ 
        //StringBuilder
        StringBuilder[] arrStringBuilder=new StringBuilder[]{new StringBuilder("Hello1"), new 
StringBuilder("Hello2"),new StringBuilder("Hello3")};
        for(StringBuilder e: arrStringBuilder){
            e.append("!"); 
        }
        for(StringBuilder e:arrStringBuilder){
            System.out.println(e);
        }
        
        //String
        String[] arrString=new String[]{"Hello1","Hello2","Hello3"};
        for(String s:arrString){
            s+="!";
        }
        for(String s:arrString){
            System.out.println(s);
        }
    }
}

结果如下(对不起,我没有添加结果!):

Hello1!
Hello2!
Hello3!
Hello1
Hello2
Hello3

P.S.:我已将打印行作为新的 for 循环取出,它仍然适用于 StringBuilder 但不适用于 String

【问题讨论】:

  • 请包括预期输出与实际输出。向我们提供可以自己运行的代码是一个好的开始,但总的来说,在问题中也有关于输出的信息会很有帮助。
  • 它不起作用,因为字符串是不可变的,您尝试分配一个新值 s = ... - 对于 StringBuilders,您不创建新值,而是更改原始值。
  • @JanezKuhar 我已经尝试在外面获取打印代码,但仍然适用于 StringBuilder 但不适用于 String 类!我刚刚添加了分号。
  • 如上所述,String 是不可变的,因此当您更改s += "!"; 时,会创建一个由局部变量@987654327 引用的新字符串(与arrString 中的不同) @。如果需要修改String数组的内容,请使用对数组元素的引用:for (int i = 0; i < arr.length; i++) { arrString[i] += "!"; }
  • 感谢大家的回复!我现在明白为什么它不适用于 String 类。因为像'code'这样的操作 str1+=str2;由 StringBuilder 类完成,我误以为它们将返回相同的初始引用。这完全是一个误解,因为将创建一个新的 StringBuilder 实例,并且 toString() 将被称为“代码”(new StringBuilder(str1).append(str2)).toString()。而这个新实例的引用值将存储在 for 循环中的局部变量中。

标签: java arrays string foreach


【解决方案1】:

e.append("!");是对方法的调用,具体目的是修改e

s+="!"; 不是方法调用。完全等价于这个:

s = s + "!";

这不会改变任何对象的状态。它只是创建一个新字符串对象(即一个字符串,其文本值是s 加上“!”的旧值),并将其分配给变量 s。您正在更改 s 持有的内容,但您没有修改 s 曾经持有的原始 String 对象。

事实证明,没有任何 String 方法可以修改 String 对象,因为 String 在设计上是不可变的。另一方面,StringBuilder 类专门用于创建和使用可变文本值。

【讨论】:

    【解决方案2】:

    在 for-each 循环的每次迭代中,变量都会获得对数组相应元素的引用。对于for(StringBuilder e:arrStringBuilder),在第一次迭代中,StringBuilder 类型的新变量e 将指向与arrStringBuilder[0] 相同的对象。然后使用这个引用调用append,它对引用earrStringBuilder[0] 指向的对象执行操作。在下一次迭代中,e 将被分配对 arrStringBuilder[1] 的引用,但在 arrStringBuilder[0] 中所做的更改将保留。

    for(String s:arrString) 的情况下,第一次迭代将创建一个指向arrString[0] 的新变量s。但是,当您执行s += '!' 时,您实际上执行的是s = s + '!',因此您为这个临时变量s 分配了对新字符串对象的引用,该对象将包含Hello1!。然而,这个新对象与原始arrString[0] 对象没有任何关系,并且在下一次迭代开始时被丢弃。你的循环是这样工作的:

    for(int i = 0; i < 3; i++) {
       // Create a temporary variable which points to the same object as arrString[i]
       String s = arrString[i];
       // Create a temporary object which keeps the result of concatenation of s and '!'
       String temporary = s + '!';
       // Replace the reference stored in s with the reference to the temporary object
       s = temporary;
       // Now there is no connection between s and arrString[i]
       // And here we just discard both temporary objects 's' and 'temporary'
       // arrString[i] object remains unchanged.
    }
    

    【讨论】:

      猜你喜欢
      • 2019-05-23
      • 1970-01-01
      • 1970-01-01
      • 2015-08-02
      • 2020-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多