Java:如何检查对象是否为空?


87

我正在创建一个从网络上检索图像的应用程序。如果无法检索图像,则应使用其他本地图像。

尝试执行以下行时:

Drawable drawable = Common.getDrawableFromUrl(this, product.getMapPath());
if (drawable.equals(null)) {
  drawable = getRandomDrawable();
}

如果drawable为null,则if(drawable.equals(null))行引发异常。

有谁知道应该如何检查drawable的值,以免在null时抛出异常并检索本地图像(执行drawable = getRandomDrawable())?


23
使用if(drawable == null)在NULL对象上调用任何方法都是NullPointerException。
diciu 2010年

3
你为什么不写通常的答案而不是评论?
迪蒙

@JaredBurrows不要以破坏问题目的的方式编辑问题中的代码!
吉尔斯(Gilles)'“ SO-别再作恶了”

@Gilles阅读我的编辑评论,使代码更具可读性。
Jared Burrows 2014年

@JaredBurrows不,您的编辑不是“格式”更改。您将作为问题对象的非工作代码更改为使问题产生争议的工作代码。
吉尔(Gilles)'所以

Answers:


35

编辑过的Java 8解决方案:

final Drawable drawable = 
    Optional.ofNullable(Common.getDrawableFromUrl(this, product.getMapPath()))
        .orElseGet(() -> getRandomDrawable());

您可以drawable final在这种情况下声明。

正如Chasmo指出的那样,Android目前不支持Java 8。因此,此解决方案仅在其他情况下可行。


7
可能不是一个好主意-您将回到Fortran 60,对条件的两面都进行评估,然后只使用其中一个。如果未使用的分支具有任何计算能力(这在大多数时候都是正确的),那么这是很糟糕的,因此它不是一种通用的方法。我将条件移到Common该类上,并允许您提供一个后备URL,并将职责保持在一起。
皮特·柯坎

1
现在该示例已完全用Java 8重写,因此我的解决方案不再遭受无用的评估(如@PeteKirkham在我的原始解决方案中指出的那样)。
迪蒙2014年

1
Android不支持Java8。它仅支持Java 7(如果有kitkat),但仍然不具有invokedynamic,只有新语法糖。除此之外,这Optional.of意味着该值不为null,因此orElseGet不必要。Optional.ofNullable在这种情况下,您应该使用。
马丁·塞勒

179
Drawable drawable = Common.getDrawableFromUrl(this, product.getMapPath());
if (drawable == null) {
    drawable = getRandomDrawable();
}

equals()方法检查值是否相等,这意味着它将比较两个对象的内容。由于null不是对象,因此在尝试将对象的内容与的内容进行比较时会崩溃null

==运营商检查参考平等,它看起来,这意味着两个对象是否实际上是相同的对象。这不要求对象实际存在。两个不存在的对象(null引用)也相等。


56
我想添加一个非常有价值的技巧:如果您要比较字符串或常量,请始终将它们放在equals子句中。(if(“ coyote” .equals(myDogString)))比(if(myDogString.equals(“ coyote”)))更好,因为在第二种情况下,myDogString可能为null并抛出NPE,而在第一种情况下,它不会myDogString是否为null无关紧要。
Thorsten S. 2010年

20
被称为尤达条件:“如果是土狼,那条狗就是……”
托马斯(Thomas)

1
我还要补充一点,由于Java 7中有一个Objects.equals()方法,因此您不必担心Yoda语法
maryokhin

21

我使用这种方法:

if (null == drawable) {
  //do stuff
} else {
  //other things
}

我发现这种方式提高了该行的可读性-当我快速阅读源文件时,我看到它是一个空检查。

关于为什么无法调用.equals()可能是的对象null; 如果你有(也就是“绘制”)的对象引用在事实上null,它并不指向堆中的对象。这意味着堆上没有对象equals()可以成功进行调用。

祝你好运!


4
我也更喜欢if(<constant> == <variable>)构造,以保护自己免受意外赋值。
斯科特

8

自己动手做

private boolean isNull(Object obj) {
    return obj == null;
}

Drawable drawable = Common.getDrawableFromUrl(this, product.getMapPath());
if (isNull(drawable)) {
    drawable = getRandomDrawable();
}

6
drawable.equals(null)

上一行在可绘制对象上调用“ equals(...)”方法。

因此,当drawable不为null且它是一个真实对象时,一切顺利,因为调用“ equals(null)”方法将返回“ false”

但是,当“ drawable”为null时,则意味着在空对象上调用“ equals(...)”方法,这意味着在不存在的对象上调用方法,从而抛出“ NullPointerException”

要检查对象是否存在并且不为空,请使用以下命令

if(drawable == null) {
    ...
    ...
}

在上述条件下,我们正在检查引用变量“ drawable”是否为null或包含某个值(对其对象的引用),以便在drawable为null的情况下它不会引发异常。

null == null

已验证。


5

if (yourObject instanceof yourClassName)将评估false是否yourObjectnull


0

捕获NullPointerException可能稍微更有效。上面的方法意味着运行时将检查空指针两次。


1
双重检查if x == null解决方案在哪里?
迪蒙

在if语句之后,运行时将在使用对象时再次检查空指针。我不知道这是否由编译器优化。
Tom R

4
这与常规知识相反,使用例外作为控制流。
詹姆斯

1
异常非常昂贵,因为它们需要创建整个stacktrace。
迪蒙2014年

0

使用Google Guava库处理is-null-check(守护程序更新)

Drawable drawable = Optional.of(Common.getDrawableFromUrl(this, product.getMapPath())).or(getRandomDrawable());

Optional今天更好地使用Java 8 。
迪蒙2014年

-1

只是向Oracle Java源开发人员提供一些想法:-)

该解决方案已经存在于.Net中,并且更具可读性!

在Visual Basic .Net中

Drawable drawable 
    = If(Common.getDrawableFromUrl(this, product.getMapPath())
        ,getRandomDrawable()
        )

在C#中

Drawable drawable 
    = Common.getDrawableFromUrl(this, product.getMapPath() 
        ?? getRandomDrawable();

这些解决方案功能强大,可作为可选Java解决方案(仅当原始值为null时才评估默认字符串)而无需使用lambda表达式,而只是添加了一个新运算符。

为了快速了解与Java解决方案的区别,我添加了2个Java解决方案

在Java中使用Optional

Drawable drawable = 
    Optional.ofNullable(Common.getDrawableFromUrl(this, product.getMapPath()))
        .orElseGet(() -> getRandomDrawable());

在Java中使用{}

Drawable drawable = Common.getDrawableFromUrl(this, product.getMapPath());
if (drawable != null)
    {
    drawable = getRandomDrawable();
    }

就个人而言,我喜欢VB.Net但我更喜欢?? C#if {}解决方案在Java中......你呢?

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.