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

Check if returned value is not null and if so assign it, in one line, with one method call

Java 到处都是这样的语句:

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

在将返回的对象分配给 dinner 之前需要两次调用 getChicken()

也可以这样写成一行:

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

但是仍然有两次调用getChicken()

当然我们可以分配一个局部变量然后再次使用三元运算符来分配它,如果它不为空,但这是两行并且不太漂亮:

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

那么有什么办法可以说:

Variable var = some value if some value is not null OR some other value;

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

因为这是如此常见的代码,所以有一个单行代码来编写它会很棒。

其他语言有这个功能吗?

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

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

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

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

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

然而,这很难读。

使用 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 到 return 的逻辑,或者 Optional.empty() 而不是 null,或者 Optional.of(myReturnObject),其中 myReturnObject 是您的 chicken.

然后你可以调用 getChicken() 如果它会 return Optional.empty() 那么 orElse(fallback) 会给你任何后备方法,在你的情况下是第二种方法。

或者在 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

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

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

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

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

您的代码将是:

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

使用你自己的

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

因为 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.

的开销

你可以使用

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

静态导入更好:

import static java.util.Objects.requireNonNullElse;

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