public class Npe {
static class Thing {
long value;
}
public static Map<Thing, Long> map;
public static void main(String[] args) {
Thing thing = new Thing();
method(null); // returns -1
method(thing); // returns 0
map = new HashMap<Thing, Long>();
method(null); // returns -1
method(thing); // NullPointerException thrown inside this method call
}
public static long method(Thing thing) {
if (thing == null) {
return -1;
}
Long v = (map == null) ? thing.value : map.get(thing); // NPE here
if (v == null) {
v = thing.value;
}
return v;
}
}
Na 4. wezwanie do method()
dostaję NullPointerException
rzucony na wskazanej linii wewnątrz method()
. Jeśli byłaby to wiersz zDlaczego to przydział powoduje NPE?
Long v = (map == null) ? thing.value : map.get(thing);
do
Long v;
if (map == null) {
v = thing.value;
} else {
v = map.get(thing);
}
mam żadnego NullPointerException
i sposób zachowuje się tak jak powinno. Pytanie brzmi: DLACZEGO ??
Wygląda mi na to, kompilator spodziewa wynikiem operatora ?
być long
tak, że jest on automatycznie unboxing (obniżania od Long
do long
) wynik wywołania map.get(thing)
(która może powrócić null
a zatem rzucać NullPointerException
). IMHO powinien oczekiwać, że wynik operatora będzie oznaczony jako Long
i będzie to oznaczać jako autoboxing (promowanie long
do Long
) thing.value
.
Jeszcze lepiej, jeśli byłaby to stwierdzenie:
Long v = (map == null) ? thing.value : map.get(thing);
do tego (odlewanie long
do Long
jawnie):
Long v = (map == null) ? (Long)thing.value : map.get(thing);
moja IDE (IntelliJ) mówi, że obsada jest zbędny, ale skompilowany kod działa zgodnie z oczekiwaniami i nie rzuca NullPointerException
! :-D
możliwy duplikat [Booleans, operatorów warunkowych i autoboxing] (http://stackoverflow.com/questions/3882095/booleans-conditional-operators-and-autoboxing) –
@DwB Twój komentarz nie jest istotny, ponieważ nie jestem młodszy programista. Twoja sugestia, aby "nie używać operatora trójskładnikowego" również jest głupia. To, że coś może być skomplikowane lub mylące, nie oznacza, że nie powinieneś go używać. Oznacza to tylko, że musisz być ostrożny i wiedzieć, co robisz. Gdyby programiści nigdy nie używali niczego, co było skomplikowane lub potencjalnie mylące, wszyscy byliby malarzami lub zamiataczami ulic lub ogrodnikami zamiast programistami ;-) –
Jeśli nie rozumiesz operatora trójskładnikowego, to, uwierz lub nie, jesteś jeszcze młodszy z Jawa. Również fakt, że coś jest skomplikowane, mylące i nie ma żadnej wartości, jest doskonałym powodem, aby go nie używać. Gdyby deweloperzy nigdy nie używali niczego, co było skomplikowane i potencjalnie mylące, produkowaliby kod, który byłby mniej niepotrzebnie skomplikowany i dezorientujący. – DwB