检查返回值是不是不为空,如果是,则在一行中使用一个方法调用将其分配

Posted

技术标签:

【中文标题】检查返回值是不是不为空,如果是,则在一行中使用一个方法调用将其分配【英文标题】:Check if returned value is not null and if so assign it, in one line, with one method call检查返回值是否不为空,如果是,则在一行中使用一个方法调用将其分配 【发布时间】:2015-06-14 18:26:07 【问题描述】:

Java 中充斥着这样的语句:

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

这需要两次调用getChicken(),然后才能将返回的对象分配给dinner

也可以这样写成一行:

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

但是,仍然有两个呼叫getChicken()

当然我们可以分配一个局部变量,然后如果它不为null,则再次使用三元运算符对其进行分配,但这是两行而不是那么漂亮:

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

那么有什么办法可以说:

变量 var = 某个值,如果某个值不为空或某个其他值 价值;

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

由于这是如此常见的代码,最好有一个单行代码来编写它。

其他语言有这个功能吗?

【问题讨论】:

不是一个真正的答案,但如果您的代码充满了这样的代码块,用默认值替换缺失值,那么您的 API 设计可能存在问题。 【参考方案1】:
dinner = cage.getChicken();
if(dinner == null) dinner = getFreeRangeChicken();

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

【讨论】:

除了缺少花括号之外,在评估中使用赋值不应该是合法的恕我直言。这段代码太难读也太容易出错了。 虽然这可能会回答这个问题,但在您的答案中加入一些文字来解释您在做什么总是一个好主意。阅读how to write a good answer。 我发现答案的第一部分是最好的解决方案,它清晰易懂,只需调用一次 getChicken【参考方案2】:

Java 缺少 coalesce 运算符,因此带有显式临时代码的代码是一次调用赋值的最佳选择。

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

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

然而,这很难阅读。

【讨论】:

像我预期的那样工作,但是我的 IDE (android studio) 要求我在“重复初始化”的标题下将其删除 ....【参考方案3】:

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

【讨论】:

【参考方案4】:

在 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

【讨论】:

【参考方案5】:

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

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

注意:Optional 的这种用法被 JDK 的架构师和可选功能的设计者明确反对。您正在分配一个新对象,并且每次都立即将其丢弃。但另一方面,它的可读性很强。

【讨论】:

如果getFreerangeChicken() 成本高,请务必使用dinner = Optional.ofNullable(cage.getChicken()) .orElseGet(()-&gt;getFreerangeChicken()); 这在 websocket 客户端中很有用:javax.websocket.CloseReason.getReasonPhrase() 在成功消息时返回 null 太糟糕了,不鼓励。我有点喜欢。 @PieterDeBie 为什么不鼓励这样做? @HeatherSawatsky,我认为只是因为,正如这个答案的发布者所指出的那样,每次使用它时都会分配一个全新的 Optional 对象,所以它比自己检查它是否为空更昂贵。 【参考方案6】:

如果你还没有使用 java 1.8 并且你不介意使用 commons-lang 你可以使用org.apache.commons.lang3.ObjectUtils#defaultIfNull

您的代码将是:

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

【讨论】:

为什么不使用 java 8? Java 8 有 Optional,它不需要外部依赖。当然,您仍然可以使用它。 很好的答案,例如当您为 Android pre API 24 开发时,Optional 调用不可用。 ObjectUtils 还提供了firstNonNull(cage.getChicken(),getFreeRangeChicken()),它读取更好的 IMO,并允许更长的后备链。 否,因为 getChicken() 和 getFreeRangeChicken() 都被计算出来了,根据问题,只需要计算一个(如果 - 否则)。【参考方案7】:

使用你自己的

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()时也会遇到同样的缺点;-)

【讨论】:

【参考方案8】:

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

【讨论】:

【参考方案9】:

你可以使用

Objects.requireNonNullElse(cage.getChicken(), getFreerangeChicken())

静态导入会更好:

import static java.util.Objects.requireNonNullElse;

requireNonNullElse(cage.getChicken(), getFreerangeChicken())

【讨论】:

以上是关于检查返回值是不是不为空,如果是,则在一行中使用一个方法调用将其分配的主要内容,如果未能解决你的问题,请参考以下文章

plsql 检查 where 子句中至少一个变量不为空

检查表单输入是不是为空,如果不是,则在按下提交按钮时显示隐藏的 div

在设置值之前检查请求输入是不是不为空

编写 CHECK CONSTRAINT 的一种更好的方法,它检查一个值是不是不为空

如何检查三个变量中是不是只有一个不为空?

如果一行不存在,则在 Python 中相应地检查并赋予一个值