CONSTANT.equals(VARIABLE)比VARIABLE.equals(CONSTANT)快吗?

时间:2012-06-06 08:55:36

标签: java

我和我的一位队友进行了一次有趣的对话。

Java中CONSTANT.equals(VARIABLE)VARIABLE.equals(CONSTANT)快吗?

我怀疑这是一个错误的陈述。但我想弄清楚这背后的定性推理是什么?

我知道在这两种情况下,表现都不会与任何重要的状态有所不同。但根据最佳实践,这是一个让我感到不舒服的建议。这就是为什么我希望在这个案例中提出一个很好的理由。

请帮助

7 个答案:

答案 0 :(得分:28)

有趣的问题。这是我写的测试:

public class EqualsTest {
    public static String CONST = "const";
    public void constEqVar(String var) {
        CONST.equals(var);
    }
    public void varEqConst(String var) {
        var.equals(CONST);
    }
}

然后我使用javac编译它:javac EqualsTest.java并使用javapjavap -c EqualsTest对其进行反汇编。

以下是javap输出的相关片段:

public void constEqVar(java.lang.String);
  Code:
   0:   getstatic       #2; //Field CONST:Ljava/lang/String;
   3:   aload_1
   4:   invokevirtual   #3; //Method java/lang/String.equals:(Ljava/lang/Object;)Z
   7:   pop
   8:   return

public void varEqConst(java.lang.String);
  Code:
   0:   aload_1
   1:   getstatic       #2; //Field CONST:Ljava/lang/String;
   4:   invokevirtual   #3; //Method java/lang/String.equals:(Ljava/lang/Object;)Z
   7:   pop
   8:   return

正如您所看到的,这两种方法之间的唯一区别是操作顺序:第一种情况下是getstatic,然后是aload_1,第二种情况是aload_1 + getstatic。

很明显,执行时间不应该依赖于此顺序。

选择const.equals(var)而不是var.equals(const)的唯一理由是避免NullPointerException

答案 1 :(得分:15)

对我而言,这不是速度问题,而是一个可靠性问题。

e.g。

"Hello".equals(a); // will never throw a NPE
a.equals("Hello"); // can throw an NPE.

当a null时,您可能更喜欢它爆炸,但通常我不喜欢。

答案 2 :(得分:2)

这仅取决于equals方法的实现。它可能更快,可能更慢,也可能是相同的......通常是相同的。此外,它不依赖于一个是变量而另一个是常量但在内容两个对象上的事实。

Constant.equals(变量)的一个优点是你不能在.equals上有一个NullPointerException

答案 3 :(得分:1)

使用字符串进行简单的测试:

final String constHello = "Hello";
final int times = 1000000000;

long constTimeStart = System.nanoTime();

for (int i = 0; i < times; ++i) {
    constHello.equals("Hello");
}

long constTimeStop = System.nanoTime();

System.out.println("constHello.equals(\"Hello\"); " + times + " times: " + (constTimeStop - constTimeStart) + " ns");


constTimeStart = System.nanoTime();

for (int i = 0; i < times; ++i) {
    "Hello".equals(constHello);
}

constTimeStop = System.nanoTime();

System.out.println("\"Hello\".equals(constHello); " + times + " times: " + (constTimeStop - constTimeStart) + " ns");

修改 如下面的评论所述,这不是一种做微观测量的好方法。切换将要执行的代码的哪一部分首先证明预热时间在这里发挥了重要作用。第一次测试总是运行得慢。在相同的代码中多次重复测试以快速修复此操作会使结果大致相同。

答案 4 :(得分:1)

如果我们将 CONSTANT键(equals方法的左侧)与任何 Object(equals方法的右侧)进行比较,则编译器可以进行比较 并给出预期的结果,但是反之亦然 Object((equals method的左侧)) Constant key((equals method的右侧))比较您的程序可能通过 NULL POINTER EXCEPTION

public static void main(String[] args) {
    String CONSTANT_KEY = "JAVA";
    String string = null;

    // CASE 1
    if (CONSTANT_KEY.equals(string)) {
        System.out.println("I am in if block");
    }

    // CASE 2   
    if (string.equals(string)) {
        System.out.println("I am in if block");
    }
}

在上面的代码中,情况1始终可以比较对象以避免NULL POINTER EXCEPTION而不是情况2。

答案 5 :(得分:0)

我想java.lang.String中的代码支持我的回答:

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = count;
        if (n == anotherString.count) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = offset;
            int j = anotherString.offset;
            while (n-- != 0) {
                if (v1[i++] != v2[j++])
                    return false;
            }
            return true;
        }
    }
    return false;
}

答案 6 :(得分:0)

一个很好的比较可以是:

private static String EXAMPLE = "Example";
private String obj = null;

案例1:

if(obj.equals(EXAMPLE) {
}

这是throw null指针异常..

案例2:

if(EXAMPLE.equals(obj)) {
}

这不会抛出空指针异常..