在Java中允许和接受hashCode和equals方法中的异常吗?

gav*_*koa 12 java exception equals hashcode nullpointerexception

一些类由框架填充(如bean).因此,您无法保证所有字段都已设置.

示例:标记为@Entity通常具有Integer id字段的类.hashCode可以写成:

public int hashCode() {
    return id.hashCode();
}
Run Code Online (Sandbox Code Playgroud)

但是defencive代码可能看起来像:

public int hashCode() {
    return (id != null) ? id.hashCode() : 0;
}
Run Code Online (Sandbox Code Playgroud)

我是否需要使用try { ... } catch (Exception e)in hashCodeequals函数对null或环绕码进行写检查?

我没有关于defencive编码的论据就是这种情况,因为它隐藏了将不一致的对象隐藏到集合中并导致延迟错误.我错了吗?

更新我写了这样的代码:

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

并运行它:

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)
Run Code Online (Sandbox Code Playgroud)

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

Jon*_*eet 9

我会亲自检查无效并使方法总是返回,没有例外.

虽然运行时异常往往不记录,并可以在任何地方被抛出,我认为这将是普遍不佳的他们被抛出equalshashCode.一方面,我完全可以看到你在完全填充之前放入地图的观点...但另一方面,很难真正知道equals将在哪里调用.

正如lc在评论中所说的那样,如果你真的想要抛出一个异常,那么抛出一个IllegalStateException明确表示这是故意的,而不是让它NullReferenceException被抛出"默认情况"会让它看起来像你只是更好没想到空场景.

  • 我同意,`IllegalStateException`将在此处最适用。 (2认同)

Ste*_*n C 7

一般来说,答案是"它取决于".

  • 如果你永远不应该看到该类的实例null,那么允许抛出NPE是合理的.NPE表示一个错误; 即你的非正式不变量被打破的情况.

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


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

  • 如果不允许nullid,那么你要小心,不要把非持久性对象到一个哈希表.

  • 如果你允许nullid,那么你有问题,如果对象添加到哈希表,然后坚持它,则hashcode可能会改变导致哈希表的破损.所以,现在你需要通过在瞬态字段中记忆对象的哈希码值来防御这种情况.而且大致出现同样的问题equals.如果在持久化对象时更改了相等性,那么最好不要在同一个哈希表中混合使用持久密钥和非持久密钥.

考虑到所有这些因素,我建议要么抛弃NPE,要么不使用/中的id字段.equalshashcode