今天我遇到了一个关于equals()方法的有趣(也是非常令人沮丧)的问题,它导致了我认为是一个经过良好测试的类崩溃,并导致了一个花了我很长时间才找到的bug.

为了完整起见,我没有使用IDE或调试器,只是使用了老式的文本编辑器和系统.时间非常有限,这是一个学校项目.

无论如何-

我正在开发一种基本的购物车,它可以装100 of 101 objects.为了实现购物车的addBook()removeBook()hasBook()方法,我想判断Cart中是否已经存在Book.所以我走了-

public boolean equals(Book b) {
    ... // More code here - null checks
    if (b.getID() == this.getID()) return true;
    else return false;
}

在测试中一切都很好.我创建了6个对象,并用数据填充它们.在Cart上执行许多添加、删除和has()操作,一切都正常.我读到你能理解,但我认为既然它起作用了,就没什么大不了的.

然后我遇到了一个问题——我需要在Book类中创建一个包含onlyIDBook对象.没有其他数据将被输入其中.基本上如下:

public boolean hasBook(int i) {
    Book b = new Book(i);
    return hasBook(b);
}

public boolean hasBook(Book b) {
    // .. more code here
    return this.books.contains(b);
}

突然之间,equals(Book b)方法不再有效.如果没有一个好的调试器,并且假设Cart类经过了正确的测试,这需要很长时间来跟踪.将equals()方法应用于以下各项后:

public boolean equals(Object o) {
    Book b = (Book) o;
    ... // The rest goes here   
}

一切又开始运转了.该方法决定不接受Book参数(即使它显然是一个Book对象)有什么原因吗?唯一的区别似乎是它是从同一个类中实例化的,并且只填充了一个数据成员.我非常非常困惑.拜托,说点什么好吗?

推荐答案

在Java中,从Object继承的equals()方法是:

public boolean equals(Object other);

换句话说,参数的类型必须为Object.这叫做overriding;您的方法public boolean equals(Book other)equals()方法执行所谓的overloading.

ArrayList使用重写的equals()方法来比较内容(例如,对于其contains()equals()方法),not个重载方法.在大多数代码中,调用没有正确覆盖Object的equals的函数是可以的,但与ArrayList不兼容.

因此,不正确重写该方法可能会导致问题.

每次我都会覆盖以下内容:

@Override
public boolean equals(Object other){
    if (other == null) return false;
    if (other == this) return true;
    if (!(other instanceof MyClass)) return false;
    MyClass otherMyClass = (MyClass)other;
    ...test other properties here...
}

使用@Override注释可以帮助很多愚蠢的错误.

只要您认为要重写超类或接口的方法,就使用它.那样的话,如果你做错了,你会得到一个编译错误.

Java相关问答推荐

Java同步小服务器

计算战舰沉船/船只的问题(Java)

如何在Spring Security中设置CustomLogin路径?

Spring安全实现多个SQL表身份验证

Java取消任务运行Oracle查询通过JDBC—连接中断,因为SQLSTATE(08006),错误代码(17002)IO错误:套接字读取中断

如何在Java中声明未使用的变量?

Java inline Double条件和值解装箱崩溃

如何在带有Micronaut的YAML中使用包含特殊字符的字符串作为键

JVM会优化这个数学运算吗?

不推荐使用的Environment.getExternalStorageDirectory().getAbsolutePath()返回的值不同于新的getExternalFilesDir(空)?

内存中的H2修剪尾随空格

如何在不删除Java中已有内容的情况下覆盖文件内容?

使用htmlunit和java单击按钮

buildDir:File!&#的getter解决方案是什么?39.被抛弃

在settings.gradle.kts和Build.gradle.kts中使用公共变量

一对多关系和ID生成

如果List是一个抽象接口,那么Collectors.toList()如何处理流呢?

使用迭代器遍历HashMap不会因IF条件而停止

按长度排序字符串数组

如何使用外部函数从Java中获取C++ struct 的返回值&;内存API