【问题标题】:Understanding for each loop in Java [duplicate]了解Java中的每个循环[重复]
【发布时间】:2010-10-10 00:28:36
【问题描述】:

下面的代码没有达到我的预期。这段代码执行后,每个字符串都为空。

String[] currentState = new String[answer.length()];
for(String x : currentState)
{
    x = "_";
}

下面的代码符合我的预期。 currentState 中的每个字符串现在都是“_”

String[] currentState = new String[answer.length()];
for (int i = 0; i < currentState.length; i++) {
    currentState[i] = "_";
}

有人可以解释为什么第一种情况不起作用吗?

【问题讨论】:

  • 想必你的意思是:String[] currentState = new String[answer.length()];

标签: java foreach


【解决方案1】:

根据设计,对于每个变量“x”(在这种情况下)并不意味着要分配给它。我很惊讶它编译得很好。

String[] currentState = new String[answer.length()]; 
for (String x : currentState) { 
    x = "_"; // x is not a reference to some element of currentState 
}

以下代码可能会显示您实际上正在做什么。请注意,这不是枚举的工作方式,但它举例说明了为什么您不能分配“x”。它是位置“i”的元素的副本。 (编辑:注意元素是引用类型,因此它是该引用的副本,分配给该副本不会更新相同的内存位置,即位置'i'处的元素)

String[] currentState = new String[answer.length()]; 
for (int i = 0; i < answer.length(); i++) { 
    String x = currentState[i];
    x = "_";
}

【讨论】:

  • 哦,所以当我这样做时 (String x : currentState),它会创建一个新的字符串 x,并在 currentState 中复制字符串的 VALUE?
  • 没关系,我明白了,我只是在切换参考
  • “我很惊讶它编译得很好”。当然它编译得很好。如果您不想分配,只需将 x 设为 final。
  • 我最近正在与遇到此问题并正在考虑为其添加 FindBugs 检测器的人交谈。虽然您可以做到这一点,但当您这样做时,它成为错误的可能性约为 100%。就个人而言,我认为这应该是编译器错误。
  • 默认情况下没有什么是最终的相同原理,保存接口数据成员,我猜(个人认为一切都应该是默认的)。
【解决方案2】:

原码:

String currentState = new String[answer.length()];

for(String x : currentState) 
{ 
    x = "_"; 
}

重写代码:

String currentState = new String[answer.length()];

for(int i = 0; i < currentState.length; i++) 
{ 
    String x;

    x = currentState[i];
    x = "_"; 
}

我将如何编写代码:

String currentState = new String[answer.length()];

for(final String x : currentState) 
{ 
    x = "_";   // compiler error
}

改写错误代码:

String currentState = new String[answer.length()];

for(int i = 0; i < currentState.length; i++) 
{ 
    final String x;

    x = currentState[i];
    x = "_";   // compiler error
}

当你做这样的事情时,使变量最终突出显示(这是一个常见的初学者错误)。尝试使您的所有变量成为最终变量(实例、类、参数、catch 中的异常等......) - 只有在您确实必须更改它们时才使它们成为非最终变量。您应该会发现 90%-95% 的变量是最终变量(初学者在开始执行此操作时会得到 20%-50%)。

【讨论】:

    【解决方案3】:

    因为x 是一个引用(或引用类型的变量)。第一段代码所做的就是将引用重新指向一个新值。例如

    String y = "Jim";
    String x = y;
    y = "Bob";
    System.out.println(x); //prints Jim
    System.out.println(y); //prints Bob
    

    您将引用 y 重新分配给“Bob”这一事实不会影响引用 x 的分配对象。

    【讨论】:

    • 在您的示例代码中,x 不是参考。这是一个变量,其值只是一个 int。将此与原始代码进行比较,其中 x is 的值是一个引用,因为 String 是一个引用类型。
    • 是的,当然。我只是想保持简单。我认为进入“引用类型变量”和“原始类型变量”的语义可能是不必要的。出于所有意图和目的,我认为 x 可以被认为是对某些值的引用。将类型更改为字符串
    • 如果你做了'y = "Bob";'会更好...更明显的是,当 x“指向 y”时,它不是指向指针的指针(有些人在使用 Java 开始时会卡住)
    【解决方案4】:

    您可以将数组转换为 List,然后像这样迭代:

    String[] currentState = new String[answer.length()];
    List<String> list = Arrays.asList(currentState);
    for(String string : list) {
       x = "_";     
    }
    

    【讨论】:

      【解决方案5】:

      对象 x[]={1,"ram",30000f,35,"account"}; for(对象 i:x) System.out.println(i); for each 用于顺序访问

      【讨论】:

        【解决方案6】:

        for each 循环的意义在于:

        List suits = ...;
        List ranks = ...;
        List sortedDeck = new ArrayList();
        for (Suit suit : suits){
            for (Rank rank : ranks)
                sortedDeck.add(new Card(suit, rank));
        }
        

        所以考虑上面你可以这样做:

        String[] currentState = new String[answer.length()];
        List<String> buffList = new ArrayList<>();
        for (String x : currentState){
                x = "_";
                buffList.add(x);
                // buffList.add(x = "_" ); will be work too
        }
        currentState = buffList.toArray(currentState);
        

        【讨论】:

          猜你喜欢
          • 2021-08-24
          • 2012-10-19
          • 2018-11-07
          • 1970-01-01
          • 2021-08-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-01-12
          相关资源
          最近更新 更多