16

チームメイトの一人と面白い会話をしました。

JavaCONSTANT.equals(VARIABLE)よりも高速ですか?VARIABLE.equals(CONSTANT)

これは虚偽の陳述だと思います。しかし、私はこれの背後にある質的な推論が何であるべきかを理解しようとしていますか?

どちらの場合も、パフォーマンスはどのような重要な状態とも変わらないことを私は知っています。しかし、それは私を不快にさせているベストプラクティスの下での推奨でした。それが、私がこの事件で提示したい良い推論に目を向けている理由です。

助けてください

4

7 に答える 7

43

興味深い質問です。これが私が書いたテストです:

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

ご覧のとおり、これら2つの方法の唯一の違いは、操作の順序です。最初のケースではgetstatic、次にaload_1、2番目のケースではaload_1+getstaticです。

実行時間がこの順序に依存してはならないことは明らかです。

を避けるconst.equals(var)よりも好む唯一の理由は。var.equals(const)NullPointerException

于 2012-06-06T09:32:10.320 に答える
21

私にとっては、速度の問題ではなく、信頼性の問題です。

例えば

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

あなたはそれがであるときに爆破することを好むかもしれnullませんが、通常私はしません。

于 2012-06-06T09:22:42.290 に答える
2

これは、equalsメソッドの実装にのみ依存します。それはより速いかもしれません、それはより遅いかもしれません、そしてそれは同じかもしれません...しばしばそれは同じです。また、一方が変数でもう一方が定数であるという事実に依存するのではなく、両方のオブジェクトのコンテンツに依存します。

Constant.equals(variable)の利点の1つは、.equalsにNullPointerExceptionを設定できないことです。

于 2012-06-06T08:58:39.267 に答える
2

CONSTANTキー(equalsメソッドの左側)を任意のObject(equalsメソッドの右側)と比較すると、コンパイラーは比較をチェックして期待される結果を得ることができますが、その逆の場合はObject((equalsメソッドの左側))Constant key((equalsメソッドの右側))と比較すると、プログラムはNULLPOINTEREXCEPTIONを通過する可能性があります。

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は、ケース2の代わりにNULL POINTER EXCEPTIONを回避するために、オブジェクトを比較するのに常に安全です。

于 2018-10-08T06:17:44.383 に答える
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");

編集: 以下のコメントで述べたように、これはマイクロ測定を行うための良い方法ではありませんでした。コードのどの部分を最初に実行するかを切り替えると、ここではウォームアップ時間が重要な役割を果たしていることがわかりました。最初のテストは常に遅くなります。同じコードでテストを複数回繰り返してクイックフィックスを行うと、結果はほぼ同じになります。

于 2012-06-06T09:22:58.767 に答える
1

1つの良い比較は次のようになります。

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

ケース1:

if(obj.equals(EXAMPLE) {
}

これはnullポインタ例外をスローします。

ケース2:

if(EXAMPLE.equals(obj)) {
}

これはnullポインタ例外をスローしません。

于 2016-10-05T05:49:42.090 に答える
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;
}
于 2012-06-06T08:59:27.323 に答える