Ostatnio czytam kod źródłowy Spring Framework. Coś, czego nie rozumiem, jest tutaj:
public Member getMember() {
// NOTE: no ternary expression to retain JDK <8 compatibility even when using
// the JDK 8 compiler (potentially selecting java.lang.reflect.Executable
// as common type, with that new base class not available on older JDKs)
if (this.method != null) {
return this.method;
}
else {
return this.constructor;
}
}
Ta metoda jest członkiem klasy org.springframework.core.MethodParameter
. Kod jest łatwy do zrozumienia, a komentarze trudne.
UWAGA: brak wyrażenia potrójnego, aby zachować zgodność z JDK <8, nawet podczas korzystania z kompilatora JDK 8 (potencjalnie wybrany
java.lang.reflect.Executable
jako typowy typ, z nową klasą bazową niedostępną na starszych JDK)
Jaka jest różnica między używaniem wyrażenia trójskładnikowego a używaniem if...else...
konstrukcji w tym kontekście?
źródło
Zostało to wprowadzone w dość starym zatwierdzeniu 3 maja 2013 roku, prawie rok przed oficjalnym wydaniem JDK-8. Kompilator był wtedy intensywnie rozwijany, więc takie problemy ze zgodnością mogły wystąpić. Wydaje mi się, że zespół Spring właśnie przetestował kompilację JDK-8 i próbował naprawić problemy, mimo że w rzeczywistości są to problemy z kompilatorem. Po oficjalnym wydaniu JDK-8 stało się to nieistotne. Teraz operator trójskładnikowy w tym kodzie działa dobrze zgodnie z oczekiwaniami (nie ma odniesienia do
Executable
klasy w skompilowanym pliku .class).Obecnie podobne rzeczy pojawiają się w JDK-9: część kodu, który można ładnie skompilować w JDK-8, nie działa z JDK-9 javac. Wydaje mi się, że większość takich problemów zostanie naprawiona do czasu premiery.
źródło
Executable
, naruszało jakiś aspekt specyfikacji? A może po prostu Oracle zdało sobie sprawę, że mogą zmienić to zachowanie w sposób, który nadal byłby zgodny ze specyfikacją i bez naruszania kompatybilności wstecznej?Executable
typ pośredni. W Javie-8 koncepcja wnioskowania o typie wyrażenia zmieniła się drastycznie i ta część została całkowicie przepisana, więc nie jest tak zaskakujące, że wczesne implementacje miały błędy.Główna różnica polega na tym, że
if
else
blok jest instrukcją, podczas gdy trójskładnik (częściej nazywany operatorem warunkowym w Javie) jest wyrażeniem .Oświadczenie może robić takie rzeczy jak
return
do rozmówcy na niektórych ścieżkach kontrolnych. W przypisaniu można użyć wyrażenia :int n = condition ? 3 : 2;
Tak więc dwa wyrażenia w trójniku po warunku muszą być koercyjne do tego samego typu. Może to powodować dziwne efekty w Javie, szczególnie przy automatycznym boksowaniu i automatycznym rzutowaniu referencji - do tego odnosi się komentarz w opublikowanym kodzie. Wymuszenie wyrażeń w twoim przypadku dotyczyłoby
java.lang.reflect.Executable
typu (ponieważ jest to typ najbardziej wyspecjalizowany ), który nie istnieje w starszych wersjach Javy.Stylistycznie powinieneś używać
if
else
bloku, jeśli kod jest podobny do instrukcji, i trójskładnika, jeśli jest podobny do wyrażenia.Oczywiście możesz sprawić, by
if
else
blok zachowywał się jak wyrażenie, jeśli używasz funkcji lambda.źródło
Na typ wartości zwracanej w wyrażeniu trójargumentowym mają wpływ klasy nadrzędne, które zmieniły się zgodnie z opisem w języku Java 8.
Trudno zrozumieć, dlaczego nie można było napisać obsady.
źródło