Подтвердить что ты не робот

Проверьте, не возвращается ли возвращаемое значение 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 = какое-то значение, если какое-то значение не равно нулю ИЛИ другое значение;

И я предполагаю, что я просто говорю о синтаксисе здесь, после того, как код скомпилирован, вероятно, не имеет большого значения, как код был написан в смысле производительности.

Поскольку это такой распространенный код, было бы здорово иметь однострочник для его написания.

Есть ли у других языков эта функция?

4b9b3361

Ответ 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();
}

Этот подход удаляет остальную часть.