检查返回值是否不为空,如果是,则通过一个方法调用在一行中分配它

问题描述 投票:0回答:10

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 = 某个值(如果某个值不为空或其他值) 值;

我想我在这里只是谈论语法,在代码编译之后,从性能角度来看代码的编写方式可能没有太大区别。

由于这是如此常见的代码,因此如果能用一行代码来编写它就太好了。

其他语言有这个功能吗?

java syntax null variable-assignment method-call
10个回答
97
投票

与 Loki 的答案相同,但更短。请记住,更短并不意味着更好。

dinner = Optional.ofNullable(cage.getChicken())
  .orElse(getFreerangeChicken());

注意:JDK 的架构师和可选功能的设计者明确不鼓励使用

Optional
。你每次都会分配一个新的对象并立即扔掉它。但另一方面,它的可读性也很高。


92
投票

Java 缺乏合并运算符,因此具有显式临时值的代码是通过单次调用进行赋值的最佳选择。

您可以使用结果变量作为临时变量,如下所示:

dinner = ((dinner = cage.getChicken()) != null) ? dinner : getFreeRangeChicken();

然而,这很难读懂。


36
投票

从 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
的开销。


23
投票

如果您不介意使用commons-lang,您可以使用org.apache.commons.lang3.ObjectUtils#defaultIfNull

您的代码将是:

dinner = ObjectUtils.defaultIfNull(cage.getChicken(),getFreeRangeChicken())

12
投票

使用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)
会给你任何后备,在你的情况下是第二种方法。


9
投票

使用你自己的

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()
    ;-)


0
投票
dinner = cage.getChicken();
if(dinner == null) dinner = getFreeRangeChicken();

if( (dinner = cage.getChicken() ) == null) dinner = getFreeRangeChicken();

0
投票

你可以使用

Objects.requireNonNullElseGet(cage.getChicken(), () -> getFreerangeChicken())

静态导入效果更好:

import static java.util.Objects.requireNonNullElseGet;

requireNonNullElseGet(cage.getChicken(), () -> getFreerangeChicken())

0
投票

简单地尝试复制列表,如果它引用 null,将触发 NullPointerException

List<String> originalList = null;
List<String> copyList = new ArrayList(originalList);

相同 NullPointerException 如果我们使用更新的 API 来获取不可变列表:

List<String> originalList = null;
List<String> copyList = List.copyOf(originalList);

这就是我们可以控制拦截异常的好处。然而,如果原始列表引用 null,我们通常只想有一个空列表。这里有几个创建原始列表副本的示例。 如果原始列表为空,它将返回一个空列表,而不是抛出异常

//List copied into immutable List
//Java 9+
copyList = List.copyOf(Objects.requireNonNullElse(originalList, List.of()));
//Java 8+
copyList = List.copyOf(Optional.ofNullable(originalList).orElse(List.of()));

//Copy provided within good old mutable ArrayList
//Java 9+
copyList = new ArrayList(Objects.requireNonNullElse(originalList, new ArrayList()));
//Java 8+
copyList = new ArrayList(Optional.ofNullable(originalList).orElse(new ArrayList()));

-1
投票

或者在 Java8 中,您可以根据需要使用 NullableNotNull 注解。

 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

© www.soinside.com 2019 - 2024. All rights reserved.