17

我一直理解Java中有两种类型的相等,

  • 值相等:使用该.equals()方法测试两个对象在非空对象引用上实现等价关系。
  • 引用相等:使用==运算符来测试两个原始类型或内存位置是否相等。

以下页面更详细地描述了这些语言基础知识。

这些链接都没有明确指定如果null比较两个对象引用的值相等应该发生什么。隐含的假设是应该抛出 a ,但这不是ObjectUtils.equals()NullPointerException方法所做的,它可能被认为是最佳实践实用方法

让我担心的是,Apache Commons似乎已经通过后门有效地将第三种平等措施引入了 Java,而本已令人困惑的情况可能会变得更加复杂。我称它为第三种相等性度量,因为它尝试测试值相等性,当失败时,它会退回到测试引用相等性。Apache Commons 相等测试与值相等和引用相等有许多相似之处,但也有明显不同。

我是否应该担心并希望尽可能避免使用ObjectUtils.equals()

是否有理由声称ObjectUtils.equals()提供了其他两种平等措施的有用结合?

选择的答案

在这个问题上似乎没有达成共识,但我决定将 Bozho 标记为正确,因为他最能引起我的注意,我现在认为这是 null-safe equals 检查的最大问题。我们都应该编写快速失败的代码来解决为什么要比较两个空对象的值相等的根本原因,而不是试图将问题扫到地毯下。

4

3 回答 3

10

这是代码ObjectUtils.equals(..)

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

ObjecUtils 文档明确指出传递的对象可以为空。

现在关于比较两个s是否true应该返回的问题。null在我看来 - 不,因为:

  • 当您比较两个对象时,您可能稍后会对它们做一些事情。这将导致一个NullPointerException
  • 传递两个nulls 进行比较意味着它们来自某个地方而不是“真实”对象,可能是由于某些问题。在这种情况下,单独比较它们是错误的 - 程序流程应该在此之前停止。
  • 在我们在这里使用的自定义库中,我们有一个名为equalOrBothNull()- 的equals方法与该实用程序中的 null 比较方法不同。
于 2010-01-25T15:36:33.950 回答
5

我是否应该担心并希望尽可能避免使用 ObjectUtils.equals() ?

不,您需要考虑的内容取决于您的要求。并且想要考虑两个 null 相等并且任何非 null 不等于 null 而不必处理 NullPointerExceptions 是一个非常非常常见的要求(例如,当您想从 setter 触发值更改事件时)。

实际上,这equals()通常是应该如何工作的,并且通常,该行为的一半已实现(Object.equals()状态为“对于任何非空引用值xx.equals(null)应返回 false。”的 API 文档) - 它不能反过来工作主要是由于技术限制(语言被设计为没有多次调度更简单)。

于 2010-01-25T15:43:51.713 回答
1

如果您对此感到担忧,那么您可以 1) 不使用此方法 2) 自己编写来包装它

public class MyObjectUtils {
    public static boolean equals(Object obj1, Object obj2) {
        return obj1 != null && obj2 != null && ObjectUtils.equals(obj1, obj2);
    }
}

对我来说,允许 null 等于 null 似乎很奇怪,但这似乎不是一个大问题。在大多数情况下,如果一个或多个对象为空,我什至不希望我的应用程序进入涉及相等测试的代码路径。

于 2010-01-25T15:38:41.357 回答