【问题标题】:How to prevent null check before equals如何防止在等于之前进行空检查
【发布时间】:2011-10-25 13:23:18
【问题描述】:

我在equals 方法中发现这样的东西相当烦人和丑陋:

if (field == null)
{
    if (other.field != null)
        return false;
}
else if ( ! field.equals(other.field))
    return false;

在 C# 中我可以这样做:

if( ! Object.Equals(field, other.field))
    return false;

在 Java 中是否有类似的东西,或者如果做这种事情的首选方法是什么?

【问题讨论】:

标签: java equals code-cleanup


【解决方案1】:

Java 7 提供java.util.Objects.equals

【讨论】:

  • 这是执行此操作的“新”推荐方式。 @Svish,如果您可以为未来的观众更改接受的答案... :)
  • 注意:对于 Android,此方法需要 minimum API >= 19。
  • 是的,这种方法有助于避免NullPointerException。请注意,Object.equals(null, null) 返回 true。
【解决方案2】:

使用 commons-lang:

org.apache.commons.lang.ObjectUtils.equals(Object object1, Object object2)

源代码:

public static boolean equals(Object object1, Object object2) {
    if (object1 == object2) {
        return true;
    }
    if ((object1 == null) || (object2 == null)) {
        return false;
    }
    return object1.equals(object2);
}

来自阿帕奇

http://commons.apache.org/lang/

这与你在 C# 中所做的差不多

【讨论】:

  • 如果你静态导入该方法(import static org.apache.commons.lang.ObjectUtils.equals;)那么你可以简单地在你的代码中写equals(a,b)
  • 太棒了。不知道那个班! ObjectUtils.hashCode 也很棒。
  • @ÓscarLópez:你不能那样做。编译器不会喜欢它(因为与Object.equals(Object) 冲突)。这就是 Guava 的 equal() 方法更适合的地方
  • @Svish:我个人喜欢 apache commons。但也请看看 NimChimpsky 在这里建议的 Google Guava:stackoverflow.com/questions/7889933/…
  • 刚刚发现他们也有EqualsBuilderHashCodeBuilder。可能刚开始使用那些...
【解决方案3】:

Guava equal 这样做的:

public static boolean equal(@Nullable Object a, @Nullable Object b) {
    return a == b || (a != null && a.equals(b));
  }

null object pattern

Guava 还有一些相关的comparison chain 和大量其他goodies

【讨论】:

  • 他们调用方法equal 而不是equals(如commons-lang)的好处在于它可以用于静态导入...
【解决方案4】:

我会这样写:

return field != null && other.field != null && field.equals(other.field);

它不如 C# 代码行优雅,但比您发布的 if 树短得多。

【讨论】:

  • 是的,如果只有一个字段可以作为解决方案。问题是当对象有几个字段要检查时。
  • 但是如果结果为真,函数之后又做了些什么呢?
【解决方案5】:

我在技术上接受所有答案。实际上,我不会在我控制的代码中使用它们中的任何一个,因为所有提供的解决方案都在解决核心问题:空值。保持你的核心模型没有空值,在这种情况下这个问题已经过时了。

在像第三方库这样的系统边界,有时必须处理空值。它们应该转化为对核心模型有意义的值。那里给出的解决方案很有帮助。

即使 Oracle 建议 equals-Methods 是 null 安全的,请考虑一下:一旦您接受 null 值,您的模型就会变得脆弱。 equals 方法不会是您检查 null 的最后一种方法。您必须在方法调用层次结构中管理空检查。方法可能不再开箱即用。很快,每个参数都会被检查为空。

我看到了双方:

一方面代码充满了 null 检查、不再信任单个参数的方法以及害怕忘记 null 检查的开发人员。

另一方面,代码具有完整的表达性语句,明确断言具有可以使用的完整功能对象,而不必担心 NullPointerExceptions。

【讨论】:

    【解决方案6】:

    作为 Project Coin 的一部分,有人提议在 Java 中添加一系列 null-safe operators。遗憾的是,它们没有进入 Java 7,也许它们会出现在 Java 8 中。Here 是它们如何工作的总体思路

    【讨论】:

      【解决方案7】:

      实际上每个人都遵循自己的方式来做到这一点,我也想在这里介绍 groovy。

      只有一种方法

      field == null ? false : true; // 所以基本上不为null的时候会返回true。

      在 groovy 中,对象有 null 安全运算符。让我们以类为例

      A { 
       String name = "test1"
      String surName = "test2"
      
      public String returnName() {
      
       return name + surName
      }
      
      }
      

      A a = null a?.name // 提到的操作符? 实际上会检查a 是否为null。然后它会调用 name。

      注意:我没有在代码中应用分号,因为这在 groovy 中不是必需的。

      【讨论】:

        【解决方案8】:

        如果为你的类实现了 toString,String.valueOf() 将解决其中的一些问题。如果指针为空,它将吐出 toString() 答案或“null”。

        【讨论】:

        • 这取决于您是否希望null 的字段值等于值“null”。我会说在大多数情况下这是可取的。它还取决于您的 toString 是否完全匹配相等匹配所需的内容......而且它也可能相当慢......
        • 我理解为什么 SQL 说 null != null,但我并不总是同意这种方法。通常,当我实现 equals 时,我可以接受 null == null。我同意速度评论,但作者想避免空检查,所以我回答了这个问题。
        • 我不是在谈论null == null。我说的是null == "null"
        • 如果我需要这个来创建字符串,那么是的:p
        【解决方案9】:

        在检查对象引用时使用 == 运算符,如果两个引用都引用同一个对象,它将返回 true。否则,如果您要查找对象内容,请使用对象的 .equals 方法。

        所以 null 意味着它在堆中没有任何内存位置。所以可以简单地用'=='操作符检查。

        【讨论】:

          猜你喜欢
          • 2011-09-15
          • 2020-03-16
          • 2017-08-10
          • 2013-08-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多