【问题标题】:Eclipse equals generation: null check missing?Eclipse 等于生成:空检查缺失?
【发布时间】:2011-11-26 02:41:44
【问题描述】:

我让 Eclipse 为我的类生成 equals 方法,它以:

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (getClass() != obj.getClass())
        return false;
[...]

在我看来,像if (obj == null) return false; 这样的支票不见了。否则,如果将空引用传递给 equals,obj.getClass() 将出现空指针异常。是我错了还是 Eclipse 错了?

【问题讨论】:

  • 可能是 Eclipse 中的一个错误,我的在这两个 if 之间添加了 null 检查。 - 这是if (obj == null) return false;,顺便说一句。 :)
  • 我的也添加了它(Indigo 3.7.0)。

标签: java eclipse


【解决方案1】:

也许你有一个旧的 Eclipse 版本。我的 Eclipse 生成了这个:

if (this == obj)
    return true;
if (obj == null)
    return false;
if (getClass() != obj.getClass())
    return false;

【讨论】:

  • 还在用 Helios,可能是这个原因。
  • 至少从 3.2 开始就是正确的。其他问题可能是问题
  • 有没有办法修改“equals”生成?也许它已经在公司完成了?
  • 因此,菜单项“Source, generate hashCode() and equals()”的行为不能改变。我现在确认 Helios 创建了空检查。在查看我同事的代码时发现它丢失了,他假装他是用 eclipse 创建的。要么他的版本太旧了,空检查就以某种方式被删除了。
【解决方案2】:

你是对的,如果 Eclipse 这样做的话。但事实并非如此。在我的机器上,Eclipse Indigo / Ubuntu,给定这个类:

public class Foo {
    private String bar;
}

Eclipse 会生成以下 equals() 方法:

@Override
public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null) return false;
    if (getClass() != obj.getClass()) return false;
    Foo other = (Foo) obj;
    if (bar == null) {
        if (other.bar != null) return false;
    } else if (!bar.equals(other.bar)) return false;
    return true;
}

为了比较,这是我为同一个类编写的 equals() 方法(使用 Guava):

@Override
public boolean equals(final Object obj) {
    return obj instanceof Foo ? Objects.equal(bar, ((Foo) obj).bar) : false;
    //          ^--- implicit null check here
}

我使用这个 Eclipse 代码模板来实现这个:

${:import(com.google.common.base.Objects)}
@Override
public boolean equals(final Object obj){
    return obj instanceof ${enclosing_type} ? Objects.equal(${field1:field}, ((${enclosing_type}) obj).${field1}) : false;
}

@Override
public int hashCode(){
    return Objects.hashCode(${field1});
}

@Override
public String toString(){
    return MoreObjects.toStringHelper(this).add("${field1}", ${field1}).toString();
}

不幸的是,我必须为每个字段的基数保留其中一个,所以我有名为 eq1(以上)、eq2、eq3、eq4 等的模板。这是一个小麻烦,但它仍然比Eclipse 生成的怪物方法。 Guava docs

【讨论】:

  • 值得注意的是,在equals() 中使用instanceof 很有可能会破坏equals() 的合约,因为它会使其不对称。
  • @dty 我知道,但我忘了指出这一点。我只会在没有进一步扩展的类中实现它。
  • a ? b : false 的简写是 a && b ;-)
  • @FredOverflow 是的,但这会降低非核心 CS 极客的代码可读性
  • 真的吗?我发现a && b 更具可读性。也许这只是我?
【解决方案3】:

是的,将null 传递为obj 将给出带有该代码的NullPointerException

【讨论】:

    【解决方案4】:

    你确实需要一个空检查。我的 Eclipse 版本生成带有空检查的 equals 方法。

    【讨论】:

      【解决方案5】:

      如果 (obj) 为 null,则 obj.getClass() 将抛出 NPE

      【讨论】:

        【解决方案6】:

        在我看来,像 if (obj == false) return false; 这样的检查不见了。

        为什么要将对象与布尔值进行比较? ;-)

        我想您可能会考虑 obj == null 检查,而这正是 Eclipse 在我的情况下生成的:

        @Override
              public boolean equals(Object obj)
              {
                if (this == obj)
                  return true;
                if (obj == null)
                  return false;
                if (getClass() != obj.getClass())
                  return false;
                TestGetClass other = (TestGetClass) obj;
                if (id != other.id)
                  return false;
                return true;
              }
        

        我使用的是 3.7 版本。无论如何,你是对的......实际上是 Eclipse...... 也是 ;-)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-09-21
          • 1970-01-01
          • 1970-01-01
          • 2021-03-18
          • 1970-01-01
          • 1970-01-01
          • 2012-09-26
          • 1970-01-01
          相关资源
          最近更新 更多