两个equals-method的行为是否相同?
(“版本1”是由eclipse ide生成的,“版本2”是我自己制作的。)
版本1:
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof CoreSale))
return false;
User other = (User) obj;
return Objects.equals(id, other.id);
}
第2版(简称):
public boolean equals(Object obj) {
// always return false, if not instance of User
if (obj instanceof CoreSale){
User other = (User) obj;
return Objects.equals(id, other.id);
}
return false;
}
obj instanceof CoreSale
是否隐式检查this == obj
,还是我必须在版本2中声明呢?
答案 0 :(得分:1)
除了晦涩的边缘情况 1 之外,这两段代码应该给出相同的答案。
它们之间的实质区别是:
this == obj
测试。obj == null
测试。if
测试以相反的顺序处理它们。
无论您将其写为obj instanceof Type
还是!(obj instanceof type)
,我都认为这无关紧要。确实,我希望JIT编译器可以根据分支通常采用的“方向”进行优化,并为这两种情况生成等效的代码。
instanceof
运算符隐式测试null
,因此不需要显式obj == null
测试。但是,我希望JIT编译器能够识别出这一点,并且不会生成用于两次检查null的本机代码。
this == obj
测试正在为一种假定为频繁发生的情况实现显式“短路”。
边缘情况意味着,如果JIT编译器尚未包含在源代码/字节代码中,则无法插入等效的短路逻辑。
目前尚不清楚短路是否会改善性能。这取决于将这些对象之一与其自身进行比较的 actual 频率...这样做的成本。
简而言之,只有this == other
测试可能会有所不同(在JIT编译之后),并且可能对性能没有好处。
但是....如果性能确实很重要,请使用实际数据进行基准测试...
1-发生边缘情况的原因是,当Objects.equals(id, other.id)
和this.id
是同一对象时,other.id
可能会引发异常或给出错误的答案。反过来,这取决于Object::equals(Object)
的实际运行时类型为id
的实际实现。