较短的equals-method与较长的equals-method一样?

时间:2019-05-13 12:47:16

标签: java equals

两个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中声明呢?

1 个答案:

答案 0 :(得分:1)

除了晦涩的边缘情况 1 之外,这两段代码应该给出相同的答案。

它们之间的实质区别是:

  1. this == obj测试。
  2. 显式obj == null测试。
  3. 最终的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的实际实现。