48

ブール式で条件付きバージョン()の代わりに無条件AND( )を使用することが好ましい場合の、Java(またはより一般的にはプログラミング)のいくつかのケースを知りたいです。&&&

&それらがどのように機能するかは知っていますが、シングルを使用する価値がある場合は考えられません。

4

11 に答える 11

61

実生活で、式の両側が非常に安価なケースを見つけたので、分岐を回避し、&代わりに無条件を使用するために 1 ナノ秒か 2 ナノ秒削りました&&。(ただし、これらは非常に高性能な数学ユーティリティでした。他のコードでこれを使用することはほとんどありませんでした。また、徹底的なベンチマークを行って優れていることを証明しなければ、とにかく使用しなかったでしょう。)

(具体的な例を挙げると、x > 0非常に安価で副作用のないものになります。とにかく非常に安価になるテストを避けるために、ブランチの予測ミスの危険を冒す必要があるでしょうか?確かに、それbooleanは最終結果が使用されるためです。とにかくブランチで、しかしif (x >= 0 && x <= 10)2つのブランチをif (x >= 0 & x <= 10)含み、1つだけを含みます.)

于 2012-07-10T11:15:36.423 に答える
20

唯一の違いは、それがわかったらすぐに評価&&||停止することです。たとえば、次のようになります。

if (a != null && a.get() != null)

でうまく動作&&&ますが、a が null の場合は NullPointerException が発生する可能性があります。

どこで使用するかについて私が考えることができる唯一のケースは&、たとえば、2 番目のオペランドに副作用がある場合です (おそらく最良の例ではありませんが、要点はわかります)。

public static void main(String[] args) {
    int i = 1;
    if (i == 0 & ++i != 2) {
    }
    System.out.println(i); //2
    i = 1;
    if (i == 0 && ++i != 2) {
    }
    System.out.println(i); //1
}

ただし、これは私には臭いコードのように見えます (どちらの場合も)。

于 2012-07-10T11:10:47.703 に答える
15

&& により、jvm は短絡評価を行うことができます。つまり、最初の引数が false の場合、わざわざ 2 番目の引数をチェックする必要はありません。

単一の & は、関係なく両側に実行されます。

したがって、不自然な例として、次のようなものがあります。

if (account.isAllowed() & logAccountAndCheckFlag(account))
    // Do something

この例では、アカウントの所有者が何かをしようとしたという事実を常にログに記録したい場合があります。

ただし、商用プログラミングで単一の & を使用したことはないと思います。

于 2012-07-10T11:11:53.303 に答える
11

ウィキペディアは短絡評価をうまく説明しています

非短絡演算子を好む場所はどこですか?

同じリンクから:

  • テストされていない 2 番目の条件は、未実行の副作用につながります
  • コード効率

ショートサーキットは、最新のプロセッサでの分岐予測のエラーにつながり、パフォーマンスを劇的に低下させる可能性があります (注目すべき例は、レイ トレーシングの軸整列ボックス交差コードを使用した高度に最適化されたレイです) [説明が必要]。一部のコンパイラはそのようなケースを検出してより高速なコードを生成できますが、C 標準に違反する可能性があるため、常に可能であるとは限りません。高度に最適化されたコードは、これを行うために他の方法を使用する必要があります (アセンブリ コードの手動使用など)。

于 2012-07-10T11:23:34.490 に答える
7

入力の検証は、考えられる 1 つのケースです。通常、フォーム内のすべてのエラーを 1 回のパスでユーザーに報告する必要があります。最初のエラーが発生した後で停止し、ユーザーに [送信] を繰り返しクリックして毎回 1 つのエラーのみを取得させるのではなく、次のようにします。

public boolean validateField(string userInput, string paramName) {
   bool valid;
   //do validation 

   if (valid) {
       //updates UI to remove error indicator (if present)
       reportValid(paramName);   
   } else {
       //updates UI to indicate a problem (color change, error icon, etc) 
       reportInvalid(paramName);  
   }      
}

public boolean validateAllInput(...) {

   boolean valid = true;
   valid = valid & validateField(userInput1, paramName1);
   valid = valid & validateField(userInput2, paramName2);
   valid = valid & validateField(userInput3, paramName3);
   valid = valid & validateField(userInput4, paramName4);
   valid = valid & validateField(userInput5, paramName5);

   return valid;
}

public void onSubmit() {

   if (validateAllInput(...)) {
       //go to next page of wizard, update database, etc
       processUserInput(userInput1, userInput2, ... );
   } 

}

public void onInput1Changed() {
   validateField(input1.Text, paramName1);
}


public void onInput2Changed() {
   validateField(input2.Text, paramName2);
}

...

確かに、 の外でロジックvalidateAllInput()をリファクタリングすることで、短絡評価の必要性を自明に回避できます。ただし、validateField() が呼び出されるたびに、抽出されたコードを呼び出す必要があります。メソッド呼び出し用に少なくとも 10 行追加します。いつものように、どちらのトレードオフが最適かというケースです。if (valid) { reportValid() ...validateField()

于 2012-07-10T13:04:15.770 に答える
7

必ず起こる副作用がある場合、それは少し醜いです。

ビット単位の AND ( &) は、ビット単位の計算に最も役立ちます。

于 2012-07-10T11:13:27.353 に答える
6

&式が些細な場合は、または|を使用して分岐を防止することで、マイクロ最適化を行うことができます。すなわち。

if(a && b) { }
if(!(a || b)) { }

と同じです

if (a) if (b) { }
if (!a) if (!b) { }

分岐が発生する可能性のある場所が 2 つあります。

ただし、無条件の&orを使用する|と、分岐は 1 つだけになります。

これが役立つかどうかは、コードが何をしているかに大きく依存します。

これを使用する場合は、コメントを付けて、なぜそれが行われたのかを明確にすることをお勧めします。

于 2012-07-10T11:39:15.623 に答える
5

単一の & の特定の用途はありませんが、次の状況を考えることができます。

if (x > 0 & someMethod(...))
{
  // code...
}

someMethod()インスタンス変数を変更する操作を行っているか、後の処理で動作に影響を与える何かを行っていると考えてください。

したがって、この場合、&&演算子を使用し、最初の条件が失敗した場合、それは決して入りませんsomeMethod()。この場合、&オペレーターは 1 人で十分です。

于 2012-07-10T11:14:11.933 に答える
3

&はビット単位の演算子であるため、1 回の操作で最大 32 個のチェックを同時に実行できます。これは、この非常に特殊なユース ケースでは大幅な速度向上になる可能性があります。多数の条件をチェックする必要があり、それを頻繁に行い、条件のボックス化/ボックス化解除のコストがチェックの数によって償却される場合、またはデータをディスク上および RAM 上の形式で保存する場合 (単一のビットマスクに 32 の条件を格納する方がスペース効率が高い)、&オペレーターは、一連の 32 個の個々の&&. たとえば、移動可能で、歩兵であり、武器のアップグレードがあり、プレイヤー 3 によって制御されているすべてのユニットを選択する場合は、次のようにします。

int MASK = CAN_MOVE | INFANTRY | CAN_ATTACK | HAS_WEAPON_UPGRADE | PLAYER_3;
for (Unit u in allunits) {
    if (u.mask & MASK == MASK) {
        ...;
    }
}

トピックの詳細については、関連する質問に関する他の回答を参照してください。

于 2012-07-11T03:11:41.860 に答える
1

ショートサーキットは、最新のプロセッサでの分岐予測のエラーにつながり、パフォーマンスを劇的に低下させる可能性があります (注目すべき例は、レイ トレーシングにおける軸整列ボックス交差コードを使用した高度に最適化されたレイです) [説明が必要]。

于 2012-07-25T08:24:57.400 に答える
1

true私が考えることができる唯一の利点は、最初の式がorに評価されても、メソッドを呼び出すかコードを実行する必要がある場合ですfalse

public boolean update()
{
    // do whatever you want here
    return true;
}

// ...

if(x == y & update()){ /* ... */}

あなたはなしでこれを行うことができますが&

if(x == y){/* ... */}
update();
于 2012-07-10T11:14:27.837 に答える