Java:タイプセーフなequals



問題

equalsは便利な仕組みなのだが、このメソッドはタイプセーフにできない。そのために、間違ったオブジェクトと比較してしまい、常にfalseが返されるというバグの原因になる。例えば、

  public static class Foo {
    int value;
    @Override
    public boolean equals(Object o) {
      if (!(o instanceof Foo)) return false;
      return ((Foo)o).value == this.value;      
    }
  }

  public static class Bar {    
  }

.......


    Foo foo = new Foo();
    Bar bar = new Bar();
    foo.equals(bar);

などとやってしまう。これは常にfalseになる。

方策1

実行時にエラーにする。

  public static class Foo {
    int value;
    public boolean equals(Object o) {
      if (!(o instanceof Foo)) throw new RuntimeException("Unexpected object");
      return ((Foo)o).value == this.value;      
    }
  }

方策2

当然以下のようには書けない。

  public static class Foo {
    int value;
    @Override
    public boolean equals(Foo o) { // <-- 引数型をObject以外にはできない
      if (!(o instanceof Foo)) return false;
      return ((Foo)o).value == this.value;      
    }
  }

仕方が無いので、別メソッドを作成する。タイプセーフにするにはこれしかないようだ。

  public static class Foo {
    int value;
    @Override
    public boolean equals(Object o) {
      if (!(o instanceof Foo)) return false;
      return ((Foo)o).value == this.value;      
    }
    public boolean eq(Foo o) {
      return equals(o);
    }
  }

参考