检查返回的值是否不为null,如果是,则使用一种方法调用在一行中进行赋值


71

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 =如果某个值不为null或某个其他值,则为某个值;

而且我想我只是在这里说语法,在代码编译之后,从性能的角度看,代码的编写方式可能并没有多大区别。

由于这是常见的代码,因此最好编写一个代码行。

其他语言是否具有此功能?


3
并不是一个真正的答案,但是如果您的代码中充满了这样的代码块,将缺失值替换为默认值,那么API的设计可能存在问题。
DenysSéguret2015年

Answers:


73

Java缺少合并运算符,因此对于具有单个调用的赋值,带有显式临时代码的最佳选择。

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

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

但是,这很难阅读。


像我预期的那样工作,但是我的IDE(android studio)要求我以“重复初始化”的标题将其删除...
MoxGeek

67

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

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

注意:OptionalJDK的架构师和Optional功能的设计师明确建议不要使用。您正在分配一个新对象,并且每次都立即将其丢弃。但另一方面,它可能非常可读。


9
如果getFreerangeChicken()价格昂贵,请确保使用dinner = Optional.ofNullable(cage.getChicken()) .orElseGet(()->getFreerangeChicken());
Matheus208 '17

这在websocket客户端中非常有用:成功javax.websocket.CloseReason.getReasonPhrase()返回null消息
Stuart Cardall,

1
太可惜了。我有点喜欢
Pieter De Bie

@PieterDeBie为什么不建议这样做?
希瑟·萨瓦斯基

@HeatherSawatsky,我认为这是因为,正如该答案的注释一样,您每次使用它时都会分配一个新的Optional对象,因此它比检查自己是否为null的开销更大。
亚历克斯·普里查德

18

如果您尚未使用Java 1.8,并且不介意使用commons-lang,则可以使用org.apache.commons.lang3.ObjectUtils#defaultIfNull

您的代码为:

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

为什么不使用Java 8?
phil294 '17

Java 8具有Optional,不需要外部依赖。当然,您仍然可以使用此功能。
Pieter De Bie

很好的答案,例如,当您为Android pre API 24开发时,Optional调用不可用。
Levite

2
ObjectUtils还提供了firstNonNull(cage.getChicken(),getFreeRangeChicken()),它读取的IMO更好,并允许更长的后备链。
Joachim Lous

13

从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


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()而不是空的,或者Optional.of(myReturnObject),在那里myReturnObject是你的chicken

然后,您可以调用getChicken(),如果它返回Optional.empty()orElse(fallback)它将给您带来任何后备,对于您而言,这是第二种方法。


3

用你自己的

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

除了花括号外,在评估中使用分配不应是合法的恕我直言。此代码太难阅读,很容易出错。
jan groth 2015年

尽管这可以回答问题,但在回答中放一些文字来解释您的工作始终是一个好主意。阅读如何写一个好的答案
耶尔- [R

1
我发现答案的第一部分是最佳解决方案,其清晰易懂,并且只拨打了一次getChicken电话
NikkyD

0

另外,在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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.