2

複数のifステートメントの代わりに論理演算子を使用していると、パフォーマンスに違いがあるのではないかと思っていました。素敵なリンクを見ましたが、これはJavaにも当てはまりますか?

4

3 に答える 3

4

次のようなクラスを作成しました

class Test{
    static java.util.Random r=new java.util.Random();
    boolean test(){
        return r.nextBoolean();
    }
    void test1(){
        if (test() && test() && test())
            System.out.println("3x yes");
    }
    void test2(){
        if (test())
            if (test()) 
                if (test())
                    System.out.println("3x yes");
    }
}

コンパイルしてからjavap -c Testで逆コンパイルし、これらの結果を得ました

class Test {
  static java.util.Random r;

  Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":
()V
       4: return

  boolean test();
    Code:
       0: getstatic     #2                  // Field r:Ljava/util/Random;
       3: invokevirtual #3                  // Method java/util/Random.nextBoole
an:()Z
       6: ireturn

  void test1();
    Code:
       0: aload_0
       1: invokevirtual #4                  // Method test:()Z
       4: ifeq          29
       7: aload_0
       8: invokevirtual #4                  // Method test:()Z
      11: ifeq          29
      14: aload_0
      15: invokevirtual #4                  // Method test:()Z
      18: ifeq          29
      21: getstatic     #5                  // Field java/lang/System.out:Ljava/
io/PrintStream;
      24: ldc           #6                  // String 3x yes
      26: invokevirtual #7                  // Method java/io/PrintStream.printl
n:(Ljava/lang/String;)V
      29: return

  void test2();
    Code:
       0: aload_0
       1: invokevirtual #4                  // Method test:()Z
       4: ifeq          29
       7: aload_0
       8: invokevirtual #4                  // Method test:()Z
      11: ifeq          29
      14: aload_0
      15: invokevirtual #4                  // Method test:()Z
      18: ifeq          29
      21: getstatic     #5                  // Field java/lang/System.out:Ljava/
io/PrintStream;
      24: ldc           #6                  // String 3x yes
      26: invokevirtual #7                  // Method java/io/PrintStream.printl
n:(Ljava/lang/String;)V
      29: return

  static {};
    Code:
       0: new           #8                  // class java/util/Random
       3: dup
       4: invokespecial #9                  // Method java/util/Random."<init>":
()V
       7: putstatic     #2                  // Field r:Ljava/util/Random;
      10: return
}

ご覧のとおり、test1とのバイトコードtest2は同じなので、使用に違いはありません。

    if (test() && test() && test())

また

    if (test())
        if (test()) 
            if (test())
于 2012-07-26T21:00:58.947 に答える
0

どちらの形式も同じコードにコンパイルされます。他の回答の提案に反して、これは「最適化」ではなく、異なるコンパイラが異なることをしたとしたら驚くべきことです。&& をコンパイルする賢明な方法は 1 つしかなく、それはそれを別の 'if' と同じように扱うことです。無意味な方法も思いつきません。

于 2012-07-27T01:37:45.673 に答える
0

これは実装に依存するため、確実にベンチマークする必要があります。

そうは言っても、ほとんどの JIT コンパイラはブール値の比較を非常に効果的に最適化できるほどスマートであるため、違いが見られる可能性はほとんどありません。

論理演算子が実質的な利点を提供する可能性が高い唯一の領域は、それらを使用してビットごとの計算を実行する場合です。これは、ハードウェア命令を悪用するブランチレス コードになる可能性があるため、非常に効率的です。

于 2012-07-26T20:57:40.687 に答える