51

そこのパフォーマンスをチェックする2つの方法を書きました

 public class Test1 {

 private String value;

 public void notNull(){
  if( value != null) {
    //do something
  }
}

public void nullNot(){
 if( null != value) {
  //do something
 }
}

}

コンパイル後にバイトコードであることを確認しました

public void notNull();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: getfield #2; //Field value:Ljava/lang/String;
4: ifnull 7
7: return
LineNumberTable: 
line 6: 0
line 9: 7

StackMapTable: number_of_entries = 1
frame_type = 7 /* same */


public void nullNot();
Code:
Stack=2, Locals=1, Args_size=1
0: aconst_null
1: aload_0
2: getfield #2; //Field value:Ljava/lang/String;
5: if_acmpeq 8
8: return
LineNumberTable: 
line 12: 0
line 15: 8

StackMapTable: number_of_entries = 1
frame_type = 8 /* same */


}

ここでは、if 条件を実装するために 2 つのオペコードが使用されます。最初のケースでは、ifnull を使用します- スタックの一番上の値が null であることを確認します- 2 番目のケースでは、if_acmpeq を使用します- スタックで上の 2 つの値が等しいことを確認します-

それで、これはパフォーマンスに影響を与えますか?(これは、null の最初の実装がパフォーマンスと読みやすさの面で優れていることを証明するのに役立ちます:))

4

16 に答える 16

81

ほとんどの最適化は JIT コンパイラーで実行時に行われるため、生成されたバイトコードを比較してもほとんど意味がありません。この場合、どちらの式も同じように高速であると推測します。多少の差があっても無視です。

これは心配する必要はありません。全体像の最適化を探します。

于 2010-03-08T00:17:40.210 に答える
21

速度 (またはメモリなど) の向上が無視できる場合は、読みやすさを犠牲にして最適化しないでください。!=null一般的に読みやすいと思うので、それを使用してください。

于 2010-03-08T00:23:11.677 に答える
12

このような質問では、JVM がどれほどスマートになるかを知るのは困難です (ただし、答えは「可能であれば通常かなりスマート」であり、この場合は非常に可能性が高いように見えます)。ただし、念のため、テストしてください。

class Nullcheck {
  public static class Fooble { }

  Fooble[] foo = {null , new Fooble(), null , null,
                  new Fooble(), null, null, new Fooble() };

  public int testFirst() {
    int sum = 0;
    for (int i=0 ; i<1000000000 ; i++) if (foo[i&0x7] != null) sum++;
    return sum;
  }

  public int testSecond() {
    int sum = 0;
    for (int i=0 ; i<1000000000 ; i++) if (null != foo[i&0x7]) sum++;
    return sum;
  }

  public void run() {
    long t0 = System.nanoTime();
    int s1 = testFirst();
    long t1 = System.nanoTime();
    int s2 = testSecond();
    long t2 = System.nanoTime();
    System.out.printf("Difference=%d; %.3f vs. %.3f ns/loop (diff=%.3f)\n",
      s2-s1,(t1-t0)*1e-9,(t2-t1)*1e-9,(t0+t2-2*t1)*1e-9);
  }

  public static void main(String[] args) {
    Nullcheck me = new Nullcheck();
    for (int i=0 ; i<5 ; i++) me.run();
  }
}

そして、私のマシンでは、これが得られます:

Difference=0; 2.574 vs. 2.583 ns/loop (diff=0.008)
Difference=0; 2.574 vs. 2.573 ns/loop (diff=-0.001)
Difference=0; 1.584 vs. 1.582 ns/loop (diff=-0.003)
Difference=0; 1.582 vs. 1.584 ns/loop (diff=0.002)
Difference=0; 1.582 vs. 1.582 ns/loop (diff=0.000)

答えは、いいえ、意味のある違いはまったくありません。(そして、JIT コンパイラーは、同じ回数の繰り返し実行後にそれぞれを高速化するための追加のトリックを見つけることができます。)


更新: 上記のコードはアドホック ベンチマークを実行します。JMHを使用する (現在は存在する) ことは、(いくつかの) マイクロベンチマークの落とし穴を回避するのに役立つ良い方法です。上記のコードは、最悪の落とし穴を回避しますが、明示的なエラーの見積もりを提供せず、時々重要になる他のさまざまなことを無視します。最近: JMH を使用してください! また、疑わしい場合は、独自のベンチマークを実行してください。詳細が重要な場合もあります — このように単純なことはあまりありませんが、本当に重要な場合は、できる限り本番環境に近い状態でチェックインする必要があります。

于 2010-03-08T03:30:42.957 に答える
3

違いはごくわずかなので、最も読みやすいものを使用してください(imo != null

于 2010-03-08T00:28:00.017 に答える
2

観点からは、パフォーマンスに大きな違いはありません。

ただし、最初に null を記述して、タイプミス エラーを検出すると便利です。

たとえば、次のコードの記述に慣れているとします。

if (obj == null)

誤って次のように記述される可能性があります。

if (obj = null)

コンパイラの観点からは、これで問題ありません。

ただし、コードを次のように書くことに慣れている場合:

if (null == obj)

そして、書くのを間違えました:

if (null = obj)

コンパイラは、その行で間違いを犯したことを知らせます。

于 2016-11-30T15:12:25.577 に答える
2

読みやすくするために (value != null) に固執します。ただし、いつでもアサーションを使用できます。

于 2010-03-08T00:29:21.170 に答える
1

最初に置くnullと余分なバイトコードが生成されるようですが、それ以外はパフォーマンスの違いはないかもしれません。

個人的には、パフォーマンスについて心配する時が来るまで、パフォーマンスについて心配することはありません。

notNull()忘れて!誤ってnull = value.

于 2010-03-08T00:20:47.423 に答える
1

究極のパフォーマンスが必要な場合は、追加のクラスやメソッドを作成しないでください。静的メソッドでさえ、Java クラス ローダーが JIT ロードする必要があるため、少し時間がかかります。

したがって、変数がnullかどうかを確認する必要があるときはいつでも、次のいずれかでテストするだけです

if (x == null)

また

if (null == x)

率直に言って、2 つのうちの 1 つを選択することによるパフォーマンスのボーナスは、不要なメソッドを導入するオーバーヘッドによって簡単に相殺されると思います。

于 2010-03-08T00:28:55.970 に答える
0

Java-8 では、Objectsクラス にObjects#nonNullObjects#isNullnullの 2 つの追加メソッドが導入されました。これらは、チェックを置き換えるために使用できます。興味深いことに、どちらも最初にオブジェクトを使用します。

public static boolean isNull(Object obj) {
    return obj == null;
}

public static boolean nonNull(Object obj) {
    return obj != null;
}

それに応じて。これが推奨される方法であることを意味していると思います (少なくともコア jdk 開発者はそのアプローチを使用しました) オブジェクト ソース コード

于 2018-04-11T11:00:38.730 に答える
0

I would prefer null != object as it makes clearly visible that it's just for null check.

于 2019-04-06T10:21:19.130 に答える
-3

バイトコードは、ソースコードを単純に翻訳したものです。

于 2010-03-08T07:14:32.160 に答える