【问题标题】:Why doesn't the overridden equals(Object) method in the Boolean class require a boolean/Boolean as an argument为什么 Boolean 类中覆盖的 equals(Object) 方法不需要 boolean/Boolean 作为参数
【发布时间】:2015-02-04 16:17:20
【问题描述】:

可能会出现以下编码错误,因为 Boolean equals(Object) 方法不需要 boolean/Boolean 参数:

private void foo() {
    Boolean isSomeConditionTrue = false;
    String doSomething = "YES";
    if(isSomeConditionTrue.equals(doSomething)) {
        // Do Something
    }
}

此代码不会“做某事”,因为编码人员忘记在谓词中将 doSomething 评估为字符串。为什么布尔等于接受 Object 而不是 boolean/Boolean 作为参数?

【问题讨论】:

  • 因为它继承自Object.equals(Object obj)
  • 将此归结为 LSP(每个对象都必须符合 Object)。然而,并非所有类型系统都以这种方式工作。我个人认为 C# 通过允许 non polymorphic 运算符重载得到了它的大部分正确性,所以 isComeConditionTrue == doSomething(在 C# 中)会导致编译器错误,而使用 Equals(在 C# 中)会有相同的问题,如此处所示。 Object 中多态 equals 的一个很好(或强制)的情况是,当用作集合的一部分时,不需要沿着“可比较”或“相等”接口进行细化。

标签: java equals


【解决方案1】:

因为equals() 是在Object 类中定义的。

没有可能的签名可以满足您的要求。
(没有使Object 通用,这会破坏目的)

【讨论】:

  • Boolean equals() 不是被覆盖来比较实际值而不是对象本身(即内存位置)吗?
  • @NathanAdams:可以,但是覆盖不能改变参数类型。 (因为你总是可以通过基类调用来传递Object
【解决方案2】:

此方法覆盖

Object.equals(Object)

因此必须接受所有对象。

同样你可以写

if (isSomeConditionTrue == doSomething) 

即使这也不可能是真的。

解决这个问题的一种方法是避免使用无论如何都不能为空的包装器。即,您的代码仅在 Boolean 不为空时才有效,因此不要使用包装器,请使用原语。

private void foo() {
    boolean isSomeConditionTrue = false;
    String doSomething = "YES";
    if(isSomeConditionTrue == doSomething) { // doesn't compile
        // Do Something
    }
}

原语不仅速度更快,而且更清楚地表明该值不能为空,并且您可以使用普通的 Java 操作,如 == != > 等。

【讨论】:

  • 为什么在source code方法中没有@Override注解?
  • @MarounMaroun 将最佳实践引入核心库可能需要一段时间。如果没有损坏,请不要修复它。即使在 Java 8u40 中也不是这样。
【解决方案3】:

equals() 是 Object 上的方法,方法协定要求参数是 Object。 equals 的约定规定,如果对象是错误的类型,则它应该返回 false。

因此,您必须先将doSomething 转换为布尔值。请注意,即使Boolean.parseBoolean(String) 也只会在字符串单词“true”忽略大小写时返回 Boolean.TRUE。 “是”不会解析为 TRUE。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-20
    • 1970-01-01
    • 2013-09-18
    • 2018-08-16
    • 1970-01-01
    • 1970-01-01
    • 2021-11-23
    相关资源
    最近更新 更多