Java: Are these 2 codes the same?
for (Player p : pl开发者_运维知识库ayers)
{
p.addCard(deck.dealCard());
p.addCard(deck.dealCard());
}
and
for (int i = 0; i < players.size() ; i++)
{
Player p = players.get(i);
p.addCard(deck.dealCard());
p.addCard(deck.dealCard());
}
The second code yeilds a null pointer exception, what can be done to make the bottom one equivalent ?
This is going to be a very wild guess: it might be possible that size()
does not yield the number of Player in players but the total capacity of players. And, the Iterator for players iterates only over the allocated items.
So to answer your question from the title, those two snippets of code are not necessarily the same. The for-each structure uses an iterator and the creator of the code could have used any implementation he considered the most suitable for whatever players' type is.
Your for-each
structure's for
equivalent should look more like this:
for (Iterator<Player> i = players.iterator(); i.hasNext(); ){
Player p = i.next();
//... Your code here
}
I can see this happening if players
is a custom java.lang.Iterable
who's get()
implementation is broken, or at any rate, behaves in an unexpected manner (different from java.util.List
's behavior).
Other that that, the only thing I can think of is that something you're not showing us in your code is causing something to go terribly wrong.
What happens if you do this?
for (Iterator<Player> playerIter = players.iterator(); playerIter.hasNext();)
{
Player p = playerIter.next();
p.addCard(deck.dealCard());
p.addCard(deck.dealCard());
}
Edit:
Just read AZ's response, and it's definitely possible that it's size()
that has the odd behavior as well.
Without knowing more details about Player
, you could do the obvious thing and check that p
is null before referencing it.
Since the line p.addCard(deck.dealCard());
is throwing the NullPointerException then either
- p is null or
- deck is null or
- dealCard() method is causing the exception somewhere.
If at all possible you should use the Iterator for Collections.
Iterator<Player> iter = players.iterator();
while(iter.hasNext()){
Player p = iter.next();
p.addCard(deck.dealcard());
//etc.
}
One scenario I can think of where a NullPointerException
will be thrown in the second case is when addCard
or dealCard
somehow changes what players
refer to (presumably neither modifies the content of players
, because that would cause a ConcurrentModificationException
in the first snippet).
Here's an example (please run this on your own if you have any doubts):
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
}
}
So as you can see, the two constructs are actually NOT exactly equivalent. The essence of the above snippet is concisely presented here:
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;
}
You will find out that the first loop went fine, while the second loop throws NullPointerException
. So while it's true most of the time, the two constructs are not exactly 100% equivalent.
The only difference with the to snippets is the method of getting a value for p. In the first java is iterating over players, in the second you are doing it explicitly. The most likely cause of the null pointer error is p being null. If deck was null both snippets would throw a null exception. The same is true of addCard and dealCard, if either method were to throw a null pointer error both snippets would do so.
It looks like java's for-each syntax is doing a check for null before executing the body of the loop.
This question talks about the difference: Java for each vs regular for -- are they equivalent?
精彩评论