Java: эти 2 кода одинаковы? - PullRequest
1 голос
/ 11 марта 2010
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 ]

3 голосов
/ 11 марта 2010

Это будет очень дикое предположение: вполне возможно, что size() дает не количество игроков в игроках, а общее количество игроков. Итератор для игроков выполняет итерации только по выделенным элементам.

Итак, чтобы ответить на ваш вопрос из заголовка, эти два фрагмента кода не обязательно совпадают. Структура for-each использует итератор, и создатель кода мог использовать любую реализацию, которую он посчитал наиболее подходящей для любого типа игроков.

Ваш for-each эквивалент for структуры должен выглядеть примерно так:

for (Iterator<Player> i = players.iterator(); i.hasNext(); ){
        Player p = i.next();
        //... Your code here
}
2 голосов
/ 11 марта 2010

Не зная более подробной информации о Player, вы могли бы сделать очевидную вещь и проверить, что p равно нулю, прежде чем ссылаться на него.

1 голос
/ 11 марта 2010

Я вижу, что это происходит, если players - это пользовательская java.lang.Iterable, чья реализация get() не работает или, во всяком случае, ведет себя неожиданным образом (отличается от java.util.List поведение).

Кроме того, единственное, о чем я могу думать, это то, что то, что вы не показываете нам в своем коде, приводит к тому, что что-то идет ужасно неправильно.

Что произойдет, если вы сделаете это?

for (Iterator<Player> playerIter = players.iterator(); playerIter.hasNext();) 
{
  Player p = playerIter.next();
  p.addCard(deck.dealCard());
  p.addCard(deck.dealCard());
}

Edit:

Просто прочитайте ответ AZ , и вполне возможно, что size() также имеет странное поведение.

1 голос
/ 11 марта 2010

Один сценарий, который я могу придумать, где NullPointerException будет выброшен во втором случае, это когда addCard или dealCard каким-то образом изменяют то, к чему относится 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. Поэтому, хотя в большинстве случаев это так, эти две конструкции не совсем точно эквивалентны .

1 голос
/ 11 марта 2010

Поскольку строка p.addCard(deck.dealCard()); выдает исключение NullPointerException, то либо

  1. р равно нулю или
  2. колода пуста или
  3. Метод dealCard () где-то вызывает исключение.

Если это вообще возможно, вы должны использовать Итератор для коллекций.

Iterator<Player> iter = players.iterator();
while(iter.hasNext()){
   Player p = iter.next();
   p.addCard(deck.dealcard());
   //etc.
}
0 голосов
/ 11 марта 2010

Единственное отличие от фрагментов to - это метод получения значения для p. В первом java перебирает игроков, во втором вы делаете это явно. Наиболее вероятная причина ошибки нулевого указателя - нулевое значение p. Если колода была нулевой, оба фрагмента выдали бы нулевое исключение. То же самое верно для addCard и dealCard, если любой из этих методов выдает ошибку нулевого указателя, оба фрагмента будут делать это.

Похоже, что синтаксис java for-each выполняет проверку на null перед выполнением тела цикла.

Этот вопрос говорит о разнице: Java для каждого против обычного для - они эквивалентны?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...