2015-08-28 38 views
6

Ciekawość, którą właśnie zauważyłem, a nie problem.Dlaczego zwracana jest wartość null (gdy oczekiwana jest wartość boolowska) w wyniku kompilacji przez operatora trójskładnikowego?

nie wolno mi napisać

public boolean x() { 
    return null; 
} 

czy to:

public boolean x() { 
    if (DEBUG) { 
    return true; 
    } else { 
    return null; 
    } 
} 

ale wolno mi napisać

public boolean x() { 
    return DEBUG ? true : null; 
} 

Dlaczego tak jest? (Wygląda na to, że wyrzuci NPE, jeśli zostanie pobrana gałąź "else".)

+0

Dzięki @Thilo. Aby wyjaśnić: pytanie brzmi, dlaczego nie potrójny konstrukt został odrzucony w taki sam sposób jak dwa pozostałe przykłady? –

+1

@MichaelKay Znowu, tylko z powodu przekleństw, czy próbowałeś 'public boolean x() { , jeśli (DEBUG) { zwraca true; } return null; } '? –

+0

możliwe powtórzenie http://stackoverflow.com/questions/978324/java-ternary-immediate-if-evaluation? – Jens

Odpowiedz

10

Jako jls stanów:

Typ wyrażenia warunkowego jest określona następująco: przypadku drugi i trzeci argumenty są tego samego typu (która może być typu NULL), to jest to typ wyrażenia warunkowego. Jeśli jeden z drugich i trzecich operandów jest typu pierwotnego T, a typ drugiego jest wynikiem zastosowania konwersji boksu (§5.1.7) do T, to typem wyrażenia warunkowego jest T.

oznacza Java pozwala null, ponieważ może on być stosowany do generowania wystąpienie Boolean, który może być do rozpakowanych boolean (odczyt sekcję o boxing w JLS więcej informacji). Ale ponieważ instancja Boolean została zainicjowana null, wywołanie booleanValue() spowoduje utworzenie NullPointerException.

2

Operator potrójny widzi, że masz dwie opcje: true i null, więc musi użyć autoboxing i sam wpisać (tj. operator warunkowy) jako Boolean (który z kolei automatycznie zostanie rozpakowany ponownie przez return).

Dokładne zasady są nieco skomplikowane, można je znaleźć in the JLS

w czasie wykonywania następnie uzyskać NullPointerException podczas unboxing wartości return.

0

Zobacz JLS-15.25

Rodzaj wyrażeniu warunkowym określa się następująco: ... Jeśli jeden z drugim i trzecim operandów jest typu null i typu drugiego jest typem odniesienia, wówczas typem wyrażenia warunkowego jest ten typ odniesienia.

...

W czasie wykonywania, pierwszy operand wyrażenie wyrażenia warunkowego jest oceniana jako pierwszy. Jeśli to konieczne, konwersja rozpakowywania jest wykonywana na wyniku.

Uzyskaną wartość logiczna jest następnie wykorzystywany do wyboru albo drugi albo trzeci wyraz operandu:

...

Wybrane wyrażenie operandu jest następnie obliczane, a wynikowa wartość jest przekształcana na typ wyrażenia warunkowego, jak określono w regułach określonych powyżej.

Konwersja może obejmować konwersję bokserską (§5.1.7) lub rozpakowywanie (§5.1.8).

Tak - zasadniczo - Twój null jest zapakowany w Boolean.

+0

Ale drugi nie jest typem referencyjnym. Przeczytaj w JLS regułę, która ma tu zastosowanie. – Thilo