Automatyczne rozpakowywanie wymaga potrójnego if-else

23

Ten fragment kodu działa dobrze: -

    Integer nullInt = null;
    if (1 <= 3) {
        Integer secondNull = nullInt;
    } else {
        Integer secondNull = -1;
    }
    System.out.println("done");

Zgłasza to jednak wyjątek o wartości zerowej, podczas gdy środowisko Eclipse ostrzega o potrzebie automatycznego rozpakowywania:

    Integer nullInt = null;
    Integer secondNull = 1 <= 3 ? nullInt : -1;
    System.out.println("done");

Dlaczego tak jest, czy ktoś może poprowadzić?

91StarSky
źródło

Odpowiedzi:

22

Typ trójskładnikowego wyrażenia warunkowego

1 <= 3 ? nullInt : -1

jest int(JLS zawiera kilka tabel opisujących typ trójskładnikowego operatora warunkowego w zależności od typów drugiego i trzeciego argumentu).

Dlatego, gdy próbuje rozpakować nullIntdo an int, generowany NullPointerExceptionjest a .

Aby uzyskać zachowanie fragmentu kodu if-else, musisz napisać:

1 <= 3 ? nullInt : Integer.valueOf(-1)

Teraz typem wyrażenia będzie Integer, więc nie nastąpi rozpakowanie.

Eran
źródło
4
Aby dodać do swojej odpowiedzi, oto wymienione tabele: docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.25
Amongalen
3

Jestem prawie pewien, że argumenty dla operatora trójskładnikowego muszą być tego samego typu. Ponieważ używasz -1 i jakiś stały nullintkompilator próbuje rozpakować, nullintaby uzyskać wartość. A następnie autobox to do przechowywania w secondNullzmiennej.

Tostery
źródło
3

Wynika to z faktu, że gdy dwa operandy operatora warunkowego ? :są typem pierwotnym i typem referencji w pudełku, następuje konwersja rozpakowywania ( JLS § 15.25.2 ):

Typ liczbowego wyrażenia warunkowego określa się w następujący sposób:

  • ...
  • Jeśli jeden z drugiego i trzeciego operandu jest typu pierwotnego T, a drugi typ jest wynikiem zastosowania konwersji boksu (§ 5.1.7) na T, wówczas typem wyrażenia warunkowego jest T.

W ogóle, zastępując ifoświadczenie o ? :wyrażeniu nie zawsze zachować rozumieniu kodeksu, ponieważ ? :samo wyrażenie musi mieć typ kompilacji. Oznacza to, że gdy typy dwóch operandów są różne, należy wykonać konwersję na jeden lub oba, aby wynik miał spójny typ czasu kompilacji.

kaya3
źródło
2

Ten działał (w Javie 1.8):

Integer secondNull = 1 <= 3 ? null : -1;
Catalina Chircu
źródło