Проверьте, не возвращается ли возвращаемое значение null, и если оно назначает его в одной строке одним вызовом метода
Java полна таких утверждений, как:
if(cage.getChicken() != null) {
dinner = cage.getChicken();
} else {
dinner = getFreeRangeChicken();
}
который выполняет два вызова getChicken()
, прежде чем возвращенный объект может быть назначен на dinner
.
Это также можно записать в одну строку примерно так:
dinner = cage.getChicken() != null? cage.getChicken() : getFreeRangeChicken();
Но, увы, есть еще два звонка getChicken()
.
Конечно, мы могли бы назначить локальную переменную, а затем снова использовать троичный оператор, чтобы назначить ее, если она не равна нулю, но это две строки и не очень красивые:
FutureMeal chicken = cage.getChicken();
dinner = chicken != null? chicken : getFreeRangeChicken();
Так есть ли способ сказать:
Переменная var = какое-то значение, если какое-то значение не равно нулю ИЛИ другое значение;
И я предполагаю, что я просто говорю о синтаксисе здесь, после того, как код скомпилирован, вероятно, не имеет большого значения, как код был написан в смысле производительности.
Поскольку это такой распространенный код, было бы здорово иметь однострочник для его написания.
Есть ли у других языков эта функция?
Ответы
Ответ 1
В Java отсутствует коалесцирующий оператор, поэтому ваш код с явным временным назначением - ваш лучший выбор для назначения с одним вызовом.
Вы можете использовать переменную результата как временную, например:
dinner = ((dinner = cage.getChicken()) != null) ? dinner : getFreeRangeChicken();
Это, однако, трудно читать.
Ответ 2
Тот же принцип, что и у Локи, но короче. Просто имейте в виду, что короче не значит автоматически, лучше.
dinner = Optional.ofNullable(cage.getChicken())
.orElse(getFreerangeChicken());
Примечание. Такое использование Optional
явно не приветствуется архитекторами JDK и разработчиками дополнительной функции. Вы выделяете свежий объект и немедленно выбрасываете его каждый раз. Но с другой стороны это может быть вполне читабельно.
Ответ 3
Если вы еще не на java 1.8, и вы не против использовать commons-lang, вы можете использовать org.apache.commons.lang3.ObjectUtils #defaultIfNull
Ваш код будет выглядеть следующим образом:
dinner = ObjectUtils.defaultIfNull(cage.getChicken(),getFreeRangeChicken())
Ответ 4
Используя Java 1.8, вы можете использовать Optional
public class Main {
public static void main(String[] args) {
//example call, the methods are just dumb templates, note they are static
FutureMeal meal = getChicken().orElse(getFreeRangeChicken());
//another possible way to call this having static methods is
FutureMeal meal = getChicken().orElseGet(Main::getFreeRangeChicken); //method reference
//or if you would use a Instance of Main and call getChicken and getFreeRangeChicken
// as nonstatic methods (assume static would be replaced with public for this)
Main m = new Main();
FutureMeal meal = m.getChicken().orElseGet(m::getFreeRangeChicken); //method reference
//or
FutureMeal meal = m.getChicken().orElse(m.getFreeRangeChicken()); //method call
}
static Optional<FutureMeal> getChicken(){
//instead of returning null, you would return Optional.empty()
//here I just return it to demonstrate
return Optional.empty();
//if you would return a valid object the following comment would be the code
//FutureMeal ret = new FutureMeal(); //your return object
//return Optional.of(ret);
}
static FutureMeal getFreeRangeChicken(){
return new FutureMeal();
}
}
Вы бы выполнили логику для getChicken
, чтобы вернуть либо Optional.empty()
вместо null, либо Optional.of(myReturnObject)
, где myReturnObject
- ваш chicken
.
Затем вы можете вызвать getChicken()
, и если он вернет Optional.empty()
, то orElse(fallback)
предоставит вам все, что было бы отложено, в вашем случае второй метод.
Ответ 5
Начиная с Java 9 у вас есть Objects # requireNonNullElse, который делает:
public static <T> T requireNonNullElse(T obj, T defaultObj) {
return (obj != null) ? obj : requireNonNull(defaultObj, "defaultObj");
}
Ваш код будет
dinner = Objects.requireNonNullElse(cage.getChicken(), getFreeRangeChicken());
Это 1 строка и вызов getChicken()
только один раз, поэтому оба требования выполнены.
Обратите внимание, что вторым аргументом также не может быть null
; этот метод вызывает ненулевое значение возвращаемого значения.
Рассмотрим также альтернативные Objects # requireNonNullElseGet:
public static <T> T requireNonNullElseGet(T obj, Supplier<? extends T> supplier)
который даже не оценивает второй аргумент, если первым не является null
, но имеет издержки на создание Supplier
.
Ответ 6
Используйте свой собственный
public static <T> T defaultWhenNull(@Nullable T object, @NonNull T def) {
return (object == null) ? def : object;
}
Пример:
defaultWhenNull(getNullableString(), "");
Преимущества
- Работает, если вы не работаете в Java8
- Работает для разработки Android с поддержкой устройств pre API 24.
- Не нужна внешняя библиотека
Недостатки
-
Всегда оценивает default value
(как показано на cond ? nonNull() : notEvaluated()
)
Это можно обойти, передав Callable вместо значения по умолчанию, но сделав его несколько более сложным и менее динамичным (например, если производительность является проблемой).
Кстати, вы сталкиваетесь с тем же недостатком при использовании Optional.orElse()
; -)
Ответ 7
dinner = cage.getChicken();
if(dinner == null) dinner = getFreeRangeChicken();
или
if( (dinner = cage.getChicken() ) == null) dinner = getFreeRangeChicken();
Ответ 8
В качестве альтернативы в Java8 вы можете использовать Nullable или NotNull Аннотации в соответствии с вашими потребностями.
public class TestingNullable {
@Nullable
public Color nullableMethod(){
//some code here
return color;
}
public void usingNullableMethod(){
// some code
Color color = nullableMethod();
// Introducing assurance of not-null resolves the problem
if (color != null) {
color.toString();
}
}
}
public class TestingNullable {
public void foo(@NotNull Object param){
//some code here
}
...
public void callingNotNullMethod() {
//some code here
// the parameter value according to the explicit contract
// cannot be null
foo(null);
}
}
http://mindprod.com/jgloss/atnullable.html
Ответ 9
Как насчет этого?
dinner = cage.getChicken();
if(dinner == null) {
dinner = getFreeRangeChicken();
}
Этот подход удаляет остальную часть.