Java:这两个代码是一样的吗?

时间:2010-03-11 03:23:33

标签: java foreach

for (Player p : players) 
{
  p.addCard(deck.dealCard());
  p.addCard(deck.dealCard());
}

  for (int i = 0; i < players.size() ; i++)
{
    Player p = players.get(i);
    p.addCard(deck.dealCard());
    p.addCard(deck.dealCard());
}

第二个代码产生一个空指针异常,可以做些什么来使底部一个等效?

6 个答案:

答案 0 :(得分:3)

这将是一个非常疯狂的猜测:size()可能不会产生玩家中玩家的数量,而是玩家的总容量。并且,玩家的迭代器仅针对分配的项目进行迭代。

所以要从标题中回答你的问题,这两段代码不一定相同。 for-each结构使用迭代器,代码的创建者可以使用他认为最适合任何玩家类型的任何实现。

您的for-each结构的for等效内容应该更像这样:

for (Iterator<Player> i = players.iterator(); i.hasNext(); ){
        Player p = i.next();
        //... Your code here
}

答案 1 :(得分:2)

在不了解有关Player的更多详细信息的情况下,您可以做一件显而易见的事情,并在引用它之前检查p是否为空。

答案 2 :(得分:1)

由于行p.addCard(deck.dealCard());抛出NullPointerException,然后是

  1. p为null或
  2. deck为null或
  3. dealCard()方法导致异常。
  4. 如果可能的话,你应该使用Iterator for Collections。

    Iterator<Player> iter = players.iterator();
    while(iter.hasNext()){
       Player p = iter.next();
       p.addCard(deck.dealcard());
       //etc.
    }
    

答案 3 :(得分:1)

我可以想到在第二种情况下会引发NullPointerException的情况是addCarddealCard以某种方式改变players所指的内容(可能两者都没有修改) players的内容,因为这会在第一个代码段中导致ConcurrentModificationException

这是一个例子(如果您有任何疑问,请自行运行):

import java.util.*;

public class ForEachVS {
    static List<Integer> players;
    static void process(int i) {
        System.out.println(i);
        players = null;
    }
    public static void main(String args[]) {
        players = Arrays.asList(1,2,3);
        for (int p : players) {
            process(p);
        } // this processes 1,2,3
        players = Arrays.asList(1,2,3);
        for (int i = 0; i < players.size(); i++) {
            process(players.get(i));
        } // this processes 1, then throws NullPointerException
    }
}

正如您所看到的,这两个结构实际上并不完全等效。以上简要介绍了上述代码片段的精髓:

    int[] arr;

    arr = new int[5];
    for (int x : arr) {
        arr = null;
    }

    arr = new int[5];
    for (int i = 0; i < arr.length; i++) {
        arr = null;
    }

你会发现第一个循环没问题,而第二个循环抛出NullPointerException。因此,虽然大部分时间都是如此,这两个结构并不完全相同

答案 4 :(得分:1)

如果players是自定义的get() java.util.Listfor (Iterator<Player> playerIter = players.iterator(); playerIter.hasNext();) { Player p = playerIter.next(); p.addCard(deck.dealCard()); p.addCard(deck.dealCard()); } 实施已被破坏,或者无论如何都以意外的方式行事(与size()不同,我可以看到这种情况发生的行为)。

除此之外,我唯一能想到的是你在代码中没有向我们展示的东西导致了一些非常糟糕的错误。

如果你这样做会怎么样?

{{1}}

编辑:

只需阅读java.lang.Iterable,它的{{1}}肯定也可能有奇怪的行为。

答案 5 :(得分:0)

与片段的唯一区别在于获取p的值的方法。在第一个java迭代玩家,在第二个你明确地做。空指针错误的最可能原因是p为null。如果deck为null,则两个片段都会抛出一个null异常。 addCard和dealCard也是如此,如果任何一种方法都抛出空指针错误,两个片段都会这样做。

看起来java的for-each语法在执行循环体之前检查null。

这个问题谈到了区别: Java for each vs regular for -- are they equivalent?