今天,我偶然发现了以下内容:
考虑两个类NewClass和NewClass1,它们具有以下“等于”方法:
新类:
@Override
public boolean equals(Object obj) {
return false;
}
public boolean equals(NewClass obj) {
return value == obj.getValue();
}
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,调用14ms对应3000ms)。起初,我认为这与“ instanceof”检查有关,但是如果我替换为“ return equals((NewClass1)obj);”,带有“ return false”;在NewClass1中,突然间它运行的速度差不多一样快。我不太了解这里发生了什么,因为在我看来,equals(Object)中的return语句永远不应真正被调用。我这是怎么了?
以下是我的“基准测试代码”,以防万一我在这里犯了一些错误:
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.");
}
最佳答案
我想这是耗时的测试实例。当您将该方法的最终返回值更改为始终返回false时,编译器可能会消除条件条件,因为无论其评估结果如何,结果都是相同的(return false)。这也将解释为什么更改最终收益根本没有任何作用,因为正如您所说的那样,绝对不应在代码路径中实际到达它。
概括地说,即使更改不在执行的代码路径上,代码更改也会通过更改编译器优化代码的方式而影响性能。