Недавно читаю исходный код Spring Framework. Что-то, чего я не могу понять, идет сюда:
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;
}
}
Этот метод является членом класса org.springframework.core.MethodParameter
. Код легко понять, а комментарии сложны.
ПРИМЕЧАНИЕ: нет тернарного выражения для сохранения совместимости с JDK <8 даже при использовании компилятора JDK 8 (потенциально выбирается
java.lang.reflect.Executable
как общий тип, при этом новый базовый класс недоступен в старых JDK)
В чем разница между использованием тернарного выражения и использованием if...else...
конструкции в этом контексте?
источник
Это было введено в довольно старый коммит 3 мая 2013 года, почти за год до официального выпуска JDK-8. В то время компилятор сильно разрабатывался, поэтому проблемы с совместимостью могли возникнуть. Думаю, команда Spring только что протестировала сборку JDK-8 и попыталась исправить проблемы, хотя на самом деле это проблемы компилятора. К официальному выпуску JDK-8 это стало неактуальным. Теперь тернарный оператор в этом коде работает нормально, как и ожидалось (ссылки на
Executable
класс в скомпилированном .class-файле нет).В настоящее время похожие вещи появляются в JDK-9: некоторый код, который может быть хорошо скомпилирован в JDK-8, не работает с JDK-9 javac. Думаю, большинство таких проблем будут исправлены до релиза.
источник
Executable
, нарушением какого-либо аспекта спецификации? Или же Oracle просто осознала, что может изменить это поведение так, чтобы оно соответствовало спецификации и не нарушало обратной совместимости?Executable
тип для промежуточного ввода. В Java-8 концепция вывода типов выражений радикально изменилась, и эта часть была полностью переписана, поэтому неудивительно, что в ранних реализациях были ошибки.Основное отличие состоит в том, что
if
else
блок - это оператор, тогда как тернарный (более известный как условный оператор в Java) - это выражение .Заявление может сделать такие вещи , как
return
к вызывающему на некоторых из каналов управления. Выражение может быть использовано в назначении:int n = condition ? 3 : 2;
Таким образом, два выражения в тернарном выражении после условия должны быть приведены к одному и тому же типу. Это может вызвать некоторые странные эффекты в Java, особенно с автоматической упаковкой и автоматическим приведением ссылок - это то, на что ссылается комментарий в опубликованном вами коде. Приведение выражений в вашем случае будет относиться к
java.lang.reflect.Executable
типу (так как это наиболее специализированный тип ), которого нет в более старых версиях Java.Стилистически вы должны использовать
if
else
блок, если код похож на инструкцию, и троичный, если он похож на выражение.Конечно, вы можете заставить
if
else
блок вести себя как выражение, если используете лямбда-функцию.источник
На тип возвращаемого значения в тернарном выражении влияют родительские классы, которые изменились, как описано в Java 8.
Трудно понять, почему нельзя было написать гипс.
источник