Java 中 hashCode 和 equals 方法中的异常是否允许并可接受?

2024-01-09

一些类由框架(如 bean)填充。所以你不能保证所有字段都已设置。

查看示例:标记为的类@Entity通常有Integer id field. hashCode可以写成:

public int hashCode() {
    return id.hashCode();
}

但防御代码可能如下所示:

public int hashCode() {
    return (id != null) ? id.hashCode() : 0;
}

我是否需要编写空代码或环绕代码检查try { ... } catch (Exception e) in hashCode and equals功能?

我没有理由支持这种情况下的防御性编码,因为它隐藏了将不一致的对象放入集合中并导致后期错误。我这个立场有错吗?

UPDATE我写了这样的代码:

import java.util.*;

class ExceptionInHashcode {

    String name;

    ExceptionInHashcode() { }
    ExceptionInHashcode(String name) { this.name = name; }

    public int hashCode() {
        // throw new IllegalStateException("xxx");
        return this.name.hashCode();
    }

    public static void main(String args[]) {
        Hashtable list = new Hashtable();
        list.put(new ExceptionInHashcode("ok"), 1);
        list.put(new ExceptionInHashcode(), 2); // fail
        System.out.println("list.size(): " + list.size());
    }
}

并运行它:

java -classpath . ExceptionInHashcode
Exception in thread "main" java.lang.NullPointerException
        at ExceptionInHashcode.hashCode(ExceptionInHashcode.java:12)
        at java.util.Hashtable.hash(Hashtable.java:262)
        at java.util.Hashtable.put(Hashtable.java:547)
        at ExceptionInHashcode.main(ExceptionInHashcode.java:18)

我认为如果对象处于错误状态,我可以尽早发现错误而不是返回零......


一般来说,答案是“视情况而定”。

  • 如果你应该never查看类的实例null对于该字段,那么允许抛出 NPE 是合理的。 NPE 表示存在错误;即你的非正式不变量被打破的情况。

  • 如果在某些情况下,实例具有null可以合理预期,那么你应该处理null情况下不抛出异常。


在这种特殊情况下,您显然正在处理以下对象:id如果对象尚未持久化,则字段可以为 null。这提出了一个棘手的问题:

  • 如果你不允许null为了id,那么你必须小心不要将非持久对象放入哈希表中。

  • 如果你允许null为了id,那么你就会遇到一个问题,如果你将一个对象添加到哈希表中然后持久化它,那么hashcode可能会发生变化,导致哈希表损坏。因此,现在您需要通过在瞬态字段中记住对象的哈希码值来防范这种情况。大致相同的问题发生在equals。如果在持久化对象时相等性发生变化,那么最好不要在同一个哈希表中混合持久化和非持久化键。

考虑到所有这些,我建议要么抛出 NPE,要么不使用id领域在equals / hashcode.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 中 hashCode 和 equals 方法中的异常是否允许并可接受? 的相关文章

随机推荐