今天,我偶然发现了以下内容:

考虑两个类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)。这也将解释为什么更改最终收益根本没有任何作用,因为正如您所说的那样,绝对不应在代码路径中实际到达它。

概括地说,即使更改不在执行的代码路径上,代码更改也会通过更改编译器优化代码的方式而影响性能。

09-26 02:36