今日、私は次のようつまずいてきました:Javaはここで私の "equals"実装と何をしていますか?
NewClass:
@Override
public boolean equals(Object obj) {
return false;
}
public boolean equals(NewClass obj) {
return value == obj.getValue();
}
NewClass1:
は以下の-methods "に等しい" を持っている二つのクラスNewClassとNewClass1を、考えてみましょう
@Override
public boolean equals(Object obj) {
if(!(obj instanceof NewClass1)) {
return false;
}
return equals((NewClass1) obj);
}
public boolean equals(NewClass1 obj) {
return value == obj.getValue();
}
私が気付くのは、NewClass1のequalsがNewClassのequalsよりも指数関数的に遅いようです10.000.000は3000msに対して14msを呼び出す)。最初は、これは "instanceof"チェックに関連していると思っていましたが、 "return equals((NewClass1)obj);" "return false;"と返すNewClass1では、突然それは多かれ少なかれ同じ速さで実行されます。私の意見では、equals(Object)のreturn文は実際には決して呼び出されるべきではないので、ここで何が起きているのかは分かりません。私はここで何が間違っていますか?通常と呼ばれることはありませんでしょう最初の例equals(NewClass)
で
public static void main(String[] args) {
// TODO code application logic here
NewClass i1 = new NewClass(1);
NewClass i2 = new NewClass(1);
NewClass i3 = new NewClass(5);
NewClass1 j1 = new NewClass1(1);
NewClass1 j2 = new NewClass1(1);
NewClass1 j3 = new NewClass1(5);
Object o1 = new Object();
Object o2 = new Object();
assert(i1.equals(i1));
assert(i1.equals(i2));
assert(i1.equals(i3) == false);
assert(i1.equals(o1) == false);
assert(j1.equals(j1));
assert(j1.equals(j2));
assert(j1.equals(j3) == false);
assert(j1.equals(o1) == false);
long start = System.currentTimeMillis();
for(int i=0; i<1000000000; i++) {
i1.equals(i1);
i1.equals(i2);
i1.equals(o1);
i1.equals(o2);
}
long end = System.currentTimeMillis();
System.out.println("Execution time was "+(end-start)+" ms.");
start = System.currentTimeMillis();
for(int i=0; i<1000000000; i++) {
j1.equals(j1);
j1.equals(j2);
j1.equals(o1);
j1.equals(o2);
}
end = System.currentTimeMillis();
System.out.println("Execution time was "+(end-start)+" ms.");
}
'instanceof'が呼び出されないように' return false; 'に置き換えるとコードが最適化されるのでしょうか? – thejh
@thejh:それは実際には意味をなさないでしょう...これは答えだったはずです。最初の有用なコメントです。私はそれをチェックします。 – fresskoma
最初の例にバグがあることに気付きましたら幸いです。使用するequals()の特定の実装は、コンパイル時に選択されます。これは、オブジェクトのタイプがコンパイル時に知られていない場合、例えば、実際に 'NewClass'インスタンスを参照する' Object'があれば、常にfalseを返します。具体的には、 'n.equals((Object)n)'はfalseです。ここでnは 'NewClass'のインスタンスです。 – JeremyP