当前位置: 首页 > 面试题库 >

关于平等的最佳实践:过载还是不过载?

夹谷英奕
2023-03-14
问题内容

考虑以下代码段:

import java.util.*;
public class EqualsOverload {
    public static void main(String[] args) {
        class Thing {
            final int x;
            Thing(int x)          { this.x = x; }
            public int hashCode() { return x; }

            public boolean equals(Thing other) { return this.x == other.x; }
        }
        List<Thing> myThings = Arrays.asList(new Thing(42));
        System.out.println(myThings.contains(new Thing(42))); // prints "false"
    }
}

注意contains返回false!我们似乎失去了我们的东西!

这个bug,当然是事实,我们不小心 过载 ,而不是 覆盖
Object.equals(Object)。如果我们改写class Thing如下,contains则按true预期返回。

        class Thing {
            final int x;
            Thing(int x)          { this.x = x; }
            public int hashCode() { return x; }

            @Override public boolean equals(Object o) {
                return (o instanceof Thing) && (this.x == ((Thing) o).x);
            }
        }

有效的Java 2nd Edition,项目36:@Override始终 使用Override批注
,使用基本上相同的参数来建议应一致使用。当然,此建议很好,因为如果我们尝试@Override equals(Thing other)在第一个代码段中进行声明,那么友好的小编译器会立即指出我们的愚蠢小错误,因为这是重载,而不是覆盖。

但是,这本书没有专门介绍的是,重载equals是不是一个好主意。本质上,有3种情况:

  • 仅过载,无过载- 几乎错误
    • 这实际上是上面的第一个片段
  • 仅覆盖(无过载)-一种修复方法
    • 这实际上是上面的第二个片段
  • 重载和覆盖组合-修复的另一种方法

以下代码段说明了第三种情况:

        class Thing {
            final int x;
            Thing(int x)          { this.x = x; }
            public int hashCode() { return x; }

            public boolean equals(Thing other) { return this.x == other.x; }
            @Override public boolean equals(Object o) {
                return (o instanceof Thing) && (this.equals((Thing) o));
            }
        }

在这里,即使我们现在有2种equals方法,也仍然只有一个相等逻辑,它位于重载中。在@Override简单地委托给过载。

所以问题是:

  • “仅覆盖”与“过载和覆盖组合”的优缺点是什么?
  • 是否有理由进行超载equals,或者这几乎肯定是一种不好的做法?

问题答案:

我看不到重载equals的情况,除了它更容易出错而且更难维护,尤其是在使用继承时。

在这里,要保持反射性,对称性和可传递性或检测它们的不一致可能非常困难,因为您始终必须了解所调用的实际equals方法。只需考虑一个大的继承层次结构,并且只有一些实现自己的重载方法的类型。

所以我想说就是不做。



 类似资料:
  • 保存package.json依赖项的最佳实践是什么? 例如,我看到很多依赖项是不固定的,比如:

  • 问题内容: 对于Spring Boot应用程序,我使用 批注 成功配置了Spring ,其中包括application.properties中带有s 的依赖项。(糟糕!我找不到示例,所以也许这会对其他人有所帮助。) 片段(如下所示)设置了上下文源,将其注入,然后自动将其连接到我的DirectoryService中。 有没有更好/更干净的方法来在Spring Boot应用中进行设置? applica

  • 对于Spring Boot应用程序,我使用注释成功地配置了Spring,包括应用程序中带有s的依赖项。财产。(呜呜!我找不到一个例子,所以这可能会帮助其他人。) 下面的代码片段设置了上下文源,将其插入到中,并将其自动连接到my DirectoryService中。 有没有更好/更干净的方法来设置在Spring Boot应用程序中? 应用属性(在类路径上): MyLdapContextSource.

  • 这里有些给使用和编写 Ansible playbook 的贴士. 你能在我们的 ansible-example repository.找到展示这些最佳实践的 playbook 样例.(注意: 这些示例用的也许不是最新版的中所有特性,但它们仍旧是极佳的参考.) Topics 最佳实践 接下来的章节将向你展示一种组织 playbook 内容方式. 你对 Ansible 的使用应该符合你的需求而不是我们

  • 处理后台任务与常规调用方法有很大的不同。本指南旨在帮助让您的后台任务平稳有效地运行。本文基于 这篇博客文章。 使任务参数小而简单 方法(任务)在调用之前会被序列化。使用 TypeConverter 类将参数转换为 JSON 字符串。如果您有复杂的实体和 / 或大对象; 包括数组,最好将它们放入数据库,然后只将其标识 (id) 传递给后台任务。 错误例子: public void Method(En