如何使用增强的 for 循环更改 String 数组中的字符串内容?

问题描述

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

解决方法

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

在第一次迭代中 for(String s:arrString) 的情况下,将创建一个指向 s 的新变量 arrString[0]。但是,当您执行 s += '!' 时,您实际上是在执行 s = s + '!',因此您将一个对新 String 对象的引用分配给此临时变量 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.
}
,

e.append("!"); 是对方法的调用,其特定目的是修改 e

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

s = s + "!";

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

事实证明,没有 String 方法可以修改 String 对象,因为根据设计,字符串是不可变的。另一方面,StringBuilder 类专门用于创建和处理可变文本值。