一些由框架填充的类(如bean)。因此,您无法保证所有字段都已设置。
查看示例:标记为@Entity
的类通常具有Integer id
字段。 hashCode
可以写成:
public int hashCode() {
return id.hashCode();
}
但是defencive代码可能如下所示:
public int hashCode() {
return (id != null) ? id.hashCode() : 0;
}
我是否需要在try { ... } catch (Exception e)
和hashCode
函数中使用equals
对空代码或环绕代码进行写入检查?
我没有关于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());
}
}
并运行它:
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)
我认为如果对象处于错误的状态,我可以提前发现错误而不是返回零...
答案 0 :(得分:9)
我会亲自检查无效并使方法始终返回,没有例外。
虽然运行时异常通常没有记录并且可以抛到任何地方,但我认为equals
和hashCode
抛出它们通常会很糟糕。一方面,我完全可以看到你在完全填充之前被放入地图的观点......但另一方面,很难真正知道equals
将被调用的地方。
正如lc在评论中所说的那样,如果你真的想抛出一个异常,那么抛出一个IllegalStateException
就可以更清楚地表明这是故意的,而不是让NullReferenceException
被抛出“默认情况下”,这使得它看起来像你没有想到空场景。
答案 1 :(得分:7)
一般来说,答案是“它取决于”。
如果永远不为该字段查看具有null
的类的实例,那么允许抛出NPE是合理的。 NPE表示一个错误;即你的非正式不变量被打破的情况。
如果在某些情况下可以合理地预期null
的实例,那么您应该处理null
案例而不会抛出异常。
在这种特殊情况下,如果对象尚未持久化,您显然正在处理id
字段可以为null的对象。这提出了一个棘手的问题:
如果null
不允许id
,则必须注意不要将非持久对象放入哈希表中。
如果您对null
允许id
,那么您遇到的问题是,如果您将对象添加到哈希表中并且然后保留它,则hashcode
可能会更改导致哈希表的破坏。所以,现在你需要通过在瞬态字段中记忆对象的哈希码值来防御这种情况。 equals
出现大致相同的问题。如果在持久化对象时相等性发生变化,那么最好不要在同一个哈希表中混合使用持久密钥和非持久密钥。
考虑到所有这些因素,我建议您抛弃该NPE,或者不使用id
/ equals
中的hashcode
字段。
答案 2 :(得分:2)
为了验证对象的状态,您应该使用Bean validation framework来确保对象的状态有效。
否 hashcode和equals方法应不抛出例外。
equals
方法必须检查无效。当创建对象时,创建者有责任确保对象处于有效状态,因此hashCode
永远不会抛出异常。对于那个bean,可以使用验证。 IMO。
UPDATE :当您使用为您创建bean的bean框架时,您必须依赖bean验证。但是否则必须由Factory
负责创建对象以确保仅创建有效实例。
答案 3 :(得分:2)
您永远不希望代码中出现空指针异常。 <强>从不即可。特别是在您自己的代码之外大量使用的函数中。 hashcode
equals
toString
不应该抛出异常。
BTW:你总是可以将id作为哈希码返回。