检查返回值是不是不为空,如果是,则在一行中使用一个方法调用将其分配
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 中,您可以根据需要使用 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
【讨论】:
【参考方案5】:与 Loki 的答案相同,但更短。请记住,更短并不意味着更好。
dinner = Optional.ofNullable(cage.getChicken())
.orElse(getFreerangeChicken());
注意:Optional
的这种用法被 JDK 的架构师和可选功能的设计者明确反对。您正在分配一个新对象,并且每次都立即将其丢弃。但另一方面,它的可读性很强。
【讨论】:
如果getFreerangeChicken()
成本高,请务必使用dinner = Optional.ofNullable(cage.getChicken()) .orElseGet(()->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())
【讨论】:
以上是关于检查返回值是不是不为空,如果是,则在一行中使用一个方法调用将其分配的主要内容,如果未能解决你的问题,请参考以下文章
检查表单输入是不是为空,如果不是,则在按下提交按钮时显示隐藏的 div