【问题标题】:Java: How to check if object is null?Java:如何检查对象是否为空?
【发布时间】:2010-01-09 10:47:10
【问题描述】:

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

在尝试执行以下行时:

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

如果drawable为null,if(drawable.equals(null))行会抛出异常。

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

【问题讨论】:

  • 使用 if(drawable==null) 在 NULL 对象上调用任何方法都是 NullPointerException。
  • 你为什么不写一个通常的答案而不是评论,diciu?
  • @JaredBurrows 不要以违背问题目的的方式编辑问题中的代码!
  • @Gilles 阅读我的编辑评论,我使代码更具可读性。
  • @JaredBurrows 不,您的编辑不是“格式”更改。您将作为问题对象的非工作代码更改为使问题没有实际意义的工作代码。

标签: java android


【解决方案1】:
Drawable drawable = Common.getDrawableFromUrl(this, product.getMapPath());
if (drawable == null) {
    drawable = getRandomDrawable();
}

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

== 运算符检查 reference 是否相等,这意味着它检查两个对象是否实际上是非常相同的对象。这不需要对象实际存在;两个不存在的对象(null 引用)也相等。

【讨论】:

  • 我想补充一个非常有价值的提示:如果您有要比较的字符串或常量,总是将它们放在等号子句的首位。 (if ("coyote".equals(myDogString))) 比 (if (myDogString.equals("coyote"))) 好得多,因为在第二种情况下 myDogString 可能为 null 并抛出 NPE 而在第一种情况下它不会'myDogString 是否为 null 无关紧要。
  • 被称为尤达条件:“如果是土狼,狗是……”
  • 我还想补充一点,从 Java 7 开始就有 Objects.equals() 方法,让你不用关心 Yoda 语法
【解决方案2】:

编辑的 Java 8 解决方案:

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

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

正如 Chasmo 指出的那样,Android 目前不支持 Java 8。所以这个解决方案只有在其他情况下才有可能。

【讨论】:

  • 可能不是一个好主意 - 您将返回到 Fortran 60,在此评估条件的两边,然后只使用一个。如果未使用的分支有任何计算,这很糟糕,这在大多数情况下都是正确的,因此它不是一个普遍有用的方法。我会将条件移至 Common 类,并允许您提供后备 URL,并将职责放在一起。
  • 该示例现在完全用 Java 8 重写,因此我的解决方案不再受到无用评估的影响(正如 @PeteKirkham 在我的原始解决方案中指出的那样)。
  • Android 不支持 Java 8。它只支持 Java 7(如果你有 kitkat)并且仍然没有 invokedynamic,只有新的语法糖。除此之外,Optional.of 暗示该值不为空,因此orElseGet 是不必要的。在这种情况下,您应该使用Optional.ofNullable
【解决方案3】:

我使用这种方法:

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

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

关于为什么你不能在一个可能是null的对象上调用.equals();如果您拥有的对象引用(即'drawable')实际上null,它并不指向堆上的对象。这意味着堆上没有可以成功调用equals() 的对象。

祝你好运!

【讨论】:

  • 我也更喜欢 if( == ) 构造来保护自己免受意外分配。
【解决方案4】:

自己动手

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

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

【讨论】:

    【解决方案5】:

    如果yourObjectnullif (yourObject instanceof yourClassName) 将评估为false

    【讨论】:

      【解决方案6】:
      drawable.equals(null)
      

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

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

      但是当“drawable”为null时,则表示在null对象上调用“equals(...)”方法,表示在不存在的对象上调用方法所以抛出“NullPointerException”

      要检查对象是否存在且不为空,请使用以下内容

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

      在上述情况下,我们正在检查引用变量“drawable”是否为空或包含一些值(对其对象的引用),因此在drawable为空的情况下它不会抛出异常作为检查

      null == null
      

      有效。

      【讨论】:

        【解决方案7】:

        使用google guava libs处理is-null-check(deamon的更新)

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

        【讨论】:

        • 今天更好地使用 Java 8 Optional
        【解决方案8】:

        只是给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 中使用可选

        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,但我更喜欢 Java 中的 ?? C#if {} 解决方案......你呢?

        【讨论】:

          【解决方案9】:

          捕获 NullPointerException 可能会更有效一些。上述方法意味着运行时检查空指针两次。

          【讨论】:

          • if x == null 解决方案中的双重检查在哪里?
          • if 语句之后,运行时会在使用对象时再次检查空指针。不过,我不知道编译器是否对此进行了优化。
          • 这违背了传统观念,使用异常作为控制流。
          • 异常非常昂贵,因为它们需要创建一个完整的堆栈跟踪。
          猜你喜欢
          • 2013-10-11
          • 1970-01-01
          • 2023-03-15
          • 2019-06-09
          • 2013-02-13
          • 1970-01-01
          • 2017-05-12
          • 1970-01-01
          相关资源
          最近更新 更多