Java論理演算子の短絡


100

どのセットがショートサーキットであり、複雑な条件式がショートサーキットであるとはどういう意味ですか?

public static void main(String[] args) {
  int x, y, z;

  x = 10;
  y = 20;
  z = 30;

  // T T
  // T F
  // F T
  // F F

  //SET A
  boolean a = (x < z) && (x == x);
  boolean b = (x < z) && (x == z);
  boolean c = (x == z) && (x < z);
  boolean d = (x == z) && (x > z);
  //SET B    
  boolean aa = (x < z) & (x == x);
  boolean bb = (x < z) & (x == z);
  boolean cc = (x == z) & (x < z);
  boolean dd = (x == z) & (x > z);

}

4
この質問を参照してください:stackoverflow.com/questions/7101992/...
Eng.Fouad

回答:


244

&&そして||、それは必要がなければ、彼らは右辺を評価していないという意味演算子は「短絡」、。

&そして|論理演算子として使用した場合、オペレータは、常に両側を評価します。

演算子ごとに短絡が発生するケースは1つだけで、それらは次のとおりです。

  • false && ...-結果はfalseそこの値に関係なくのみ存在する可能性があるため、右側が何であるかを知る必要はありません
  • true || ...-結果はtrueそこの値に関係なくのみ存在する可能性があるため、右側が何であるかを知る必要はありません

簡単な例で動作を比較してみましょう:

public boolean longerThan(String input, int length) {
    return input != null && input.length() > length;
}

public boolean longerThan(String input, int length) {
    return input != null & input.length() > length;
}

2番目のバージョンは非短絡演算子&を使用し、NullPointerExceptionif inputis をスローしますnullが、1番目のバージョンはfalse例外なく戻ります。


9
この答えを少し拡張したいと思います。&=演算子はx = x&式の省略形であり、したがって、ショートサーキットではありません。| =演算子についても同様です。
Stormcloud 2015

11
強調したいことがあります。と&は二項演算子ですが、&&と||は 条件付き(論理)演算子です。| &&は、ブール値だけでなく、&&および|| ブール値でのみ機能します。
神話

1
右側の式を評価しないだけでなく、評価するものがあるためにコードが実行されません。これは、副作用が発生するかどうかを理解するための重要なポイントです。
mckenzm

@mckenzm評価と実行の違いは何ですか?
クローネン

@Kronenを実行すると、評価以上の結果が生じる可能性があり、例外や遅延などの副作用が発生する可能性があります。この例には関係ありません。
mckenzm

9

SET Aは、短絡ブール演算子を使用します。

ブール演算子のコンテキストで「短絡」とは、ブールb1、b2、...、bnのセットの場合、これらのブールの最初の値がtrueになるとすぐに、短絡バージョンが評価を停止することです(|| )またはfalse(&&)。

例えば:

// 2 == 2 will never get evaluated because it is already clear from evaluating
// 1 != 1 that the result will be false.
(1 != 1) && (2 == 2)

// 2 != 2 will never get evaluated because it is already clear from evaluating
// 1 == 1 that the result will be true.
(1 == 1) || (2 != 2)

これがの場合であり&&||動作が異なり、trueを返す最初のオペランドの評価が停止することを指定してください;)
fge

1
実際には、本当に完全なものにするために、すべての&&||&そして|左から右に評価されます。ブール値のセットb1、b2、...、bnの場合、これらのブール値の最初の値がtrue(||)またはfalse(&&)になると、短絡バージョンは評価を停止します。Bah、原則はそこにあります;)
2012年

@fge:はい、もちろんあなたは正しいです。あなたの定義は私のものより正確です。私はあなたのコメントの文で私の答えを更新しました。よろしくお願いします。
afrischke 2012年

心配する必要はありません。知識が共有されなければ価値はありません。
2012年

4

短絡は、最初のオペレーターが最終結果を決定した場合、2番目のオペレーターがチェックされないことを意味します。

たとえば、式は次のとおりです。誤り

||の場合、必要なのは片側だけです Trueになる。したがって、左側がtrueの場合、右側をチェックしても意味がないため、まったくチェックされません。

同様に、False && True

&&の場合、両側がTrueである必要があります。したがって、左側がFalseの場合、右側をチェックしても意味がありません。答えはFalseでなければなりません。したがって、それはまったくチェックされません。


4
boolean a = (x < z) && (x == x);

この種類は短絡(x < z)します。つまり、falseと評価された場合、後者は評価されず、afalseと&&評価され(x == x)ます。それ以外の場合、も評価されます。

& ビットごとの演算子ですが、短絡しないブールAND演算子でもあります。

次のような方法でテストできます(それぞれの場合にメソッドが呼び出される回数を確認してください)。

public static boolean getFalse() {
    System.out.println("Method");
    return false;
}

public static void main(String[] args) {
    if(getFalse() && getFalse()) { }        
    System.out.println("=============================");        
    if(getFalse() & getFalse()) { }
}

-1あなたの答えは、それ&がビットごとの演算子にすぎないことを示唆していますが、それは真実ではありません。それはまた、ブール「または」演算子。
ボヘミアン

@ボヘミアン:頭を上げてくれてありがとう。true & falsefalseと評価されます。この「ブール」または「演算子」について説明していただけますか?私があなたが言っていることを理解していないのかもしれません。
Bhesh Gurung、2012

すみません-私はブール値を意味してANDいましたOR。つまりtrue & false、有効な構文です。-1削除:)
ボヘミアン

4

平野用語では、短絡、あなたがそれに答えることができなくなった変更を知っていれば、評価を停止する手段を。たとえば、論理ANDsのチェーンを評価していて、FALSEそのチェーンの途中でが見つかった場合、チェーン内の残りの式の値が何であっても、結果がfalseになることがわかります。同じことがORsのチェーンにも当てはまります。TRUEたら、すぐに答えがわかるので、残りの式の評価をスキップできます。

&&代わりに&との||代わりにを使用して、短絡することをJavaに指示します|。あなたの投稿の最初のセットは短絡です。

これは、いくつかのCPUサイクルを節約する試み以上のものであることに注意してください。

if (mystring != null && mystring.indexOf('+') > 0) {
    ...
}

ショートサーキットは、正しい操作とクラッシュ(mystringがnullの場合)の違いを意味します。


2

Javaには、他のほとんどのコンピューター言語にはない2つの興味深いブール演算子が用意されています。ANDおよびORのこれらの2次バージョンは、短絡論理演算子と呼ばれます。前の表からわかるように、Bが何であっても、Aがtrueの場合、OR演算子はtrueになります。

同様に、Bが何であっても、Aがfalseの場合、AND演算子はfalseになります。||および&&フォームを使用する場合、|および&これらの演算子の形式を、Javaは右のオペランドのみを評価するために気にしないだろう。これは、適切に機能するために、右側のオペランドが左側のtrueまたはfalseに依存している場合に非常に役立ちます。

たとえば、次のコードフラグメントは、短絡論理評価を利用して、除算演算が評価される前に有効であることを確認する方法を示しています。

if ( denom != 0 && num / denom >10)

AND(&&)の短絡形式が使用されているため、ランタイム例外がゼロで除算される原因となるリスクはありません。このコード行が&AND の単一バージョンを使用して記述されている場合、両側を評価する必要があり、次の場合にランタイム例外が発生します。denomがゼロのます。

ブール論理を含む場合は、ANDおよびORの短絡形式を使用して、ビット単位の演算専用の1文字バージョンを残すのが標準的な方法です。ただし、このルールには例外があります。たとえば、次のステートメントについて考えてみます。

 if ( c==1 & e++ < 100 ) d = 100;

ここで、singleを使用&すると、インクリメント操作が1に等しいeかどうかに適用されcます。


2

論理OR:-少なくとも1つのオペランドがtrueと評価された場合、trueを返します。OR演算子を適用する前に、両方のオペランドが評価されます。

ショートサーキットOR:-左側のオペランドがtrueを返す場合、右側のオペランドを評価せずにtrueを返します。


2

&&&演算子の間にはいくつかの違いがあります。およびに同じ違いが適用さ|||ます。覚えておくべき最も重要なこと&&は、ブール演算にのみ適用される論理演算子で&あり、ビット単位であるということです。整数型だけでなく、真偽値に適用される演算子。

論理演算を使用すると、短絡を行うことができます(の最初のオペランドのような特定のケースであるため&&であることfalse、または最初のオペランド||であることtrue)、あなたは、式の残りの部分を評価する必要はありません。これは、チェックなどの作業に非常に役立ちます。null、フィールドまたはメソッドにアクセスする前にしたり、ゼロで除算する前に潜在的なゼロをチェックしたりするます。複雑な式の場合、式の各部分は同じ方法で再帰的に評価されます。たとえば、次の場合:

(7 == 8) || ((1 == 3) &&(4 == 4))

強調された部分のみが評価されます。計算する||場合は、最初のチェックを7 == 8ですtrue。もしそうなら、右側は完全にスキップされます。右側1 == 3は、かどうかのみをチェックしますfalse。それがあるので、4 == 4チェックする必要があり、そして式全体の評価さにしませんfalse。左側がの場合true、たとえばの7 == 7代わりに7 == 8||式全体がtrue無関係であるため、右側全体がスキップされます。

ビット単位の演算では、実際にはビットを組み合わせるだけなので、すべてのオペランドを評価する必要があります。ブール値は、内部ではどのように機能するかに関係なく、Javaでは実質的に1ビット整数であり、その1つの特殊なケースでビット演算子の短絡を実行できるのは単なる偶然です。一般的な整数&または|演算を短絡できないのは、一部のビットがオンになっている場合と、いずれかのオペランドでオフになっている場合があるためです。のようなもの1 & 2はゼロをもたらしますが、両方のオペランドを評価せずにそれを知る方法はありません。


1
if(demon!=0&& num/demon>10)

AND(&&)の短絡形式が使用されているため、demonがゼロの場合にランタイム例外が発生するリスクはありません。

参照 ハーバート・シルトによるJava 2第5版

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.