Java のショートカット「or-代入」(|=) 演算子
-
21-09-2019 - |
質問
Java で行うべき長い比較があり、それらのうちの 1 つ以上が正しいと判明するかどうかを知りたいと思っています。比較の文字列は長くて読みにくかったので、読みやすくするために分割し、自動的にショートカット演算子を使用するようになりました。 |=
それよりも negativeValue = negativeValue || boolean
.
boolean negativeValue = false;
negativeValue |= (defaultStock < 0);
negativeValue |= (defaultWholesale < 0);
negativeValue |= (defaultRetail < 0);
negativeValue |= (defaultDelivery < 0);
私が期待する negativeValue
いずれかのdefault<something>値が負の場合はtrueになります。これは有効ですか?期待どおりの結果が得られるでしょうか?Sun のサイトやスタックオーバーフローでは言及されていませんでしたが、Eclipse では問題ないようで、コードはコンパイルされて実行されます。
同様に、いくつかの論理交差を実行したい場合は、次のように使用できますか? &=
の代わりに &&
?
解決
の |=
は複合代入演算子 (JLS 15.26.2) ブール論理演算子の場合 |
(JLS 15.22.2);条件付き or と混同しないでください ||
(JLS 15.24)。もあります &=
そして ^=
ブール論理値の複合代入バージョンに対応します。 &
そして ^
それぞれ。
言い換えれば、 boolean b1, b2
, 、これら 2 つは同等です。
b1 |= b2;
b1 = b1 | b2;
論理演算子の違い (&
そして |
) 条件付き対応物 (&&
そして ||
)前者は「短絡」しないということです。後者はそうします。あれは:
&
そして|
いつも 両方のオペランドを評価します&&
そして||
右側のオペランドを評価する 条件付きで;右オペランドは、その値が二項演算の結果に影響を与える可能性がある場合にのみ評価されます。つまり、次の場合、右側のオペランドは評価されません。- の左オペランド
&&
と評価されるfalse
- (右のオペランドが何に評価されるかに関係なく、式全体は
false
)
- (右のオペランドが何に評価されるかに関係なく、式全体は
- の左オペランド
||
と評価されるtrue
- (右のオペランドが何に評価されるかに関係なく、式全体は
true
)
- (右のオペランドが何に評価されるかに関係なく、式全体は
- の左オペランド
元の質問に戻ると、はい、その構造は有効ですが、 |=
は正確に同等のショートカットではありません =
そして ||
, 、あなたが望むものを計算します。の右側から |=
使用中の演算子は単純な整数比較演算です。 |
短絡しないことは重要ではありません。
短絡が必要な場合、または必要な場合もありますが、あなたのシナリオはそれらの 1 つではありません。
他の言語とは異なり、Java には &&=
そして ||=
. 。これは質問で議論されました Java には、条件付き and および条件付き or 演算子の複合代入バージョンがないのはなぜですか?(&&=、||=).
他のヒント
それは「ショートカット」ではありません(または短絡)という方法で、演算子||そして&&(彼らはすでにLHSに基づいて結果を知っていれば、その中で彼らはRHSを評価しません)されているが、それはの作業の面で何をしたい行います。
text
がnullの場合の差の一例として、このコードは、罰金になります。
boolean nullOrEmpty = text == null || text.equals("")
これはないでしょうに対します:
boolean nullOrEmpty = false;
nullOrEmpty |= text == null;
nullOrEmpty |= text.equals(""); // Throws exception if text is null
(もちろん、あなたがその特定のケースのために"".equals(text)
を行うことができます - 。私はちょうど原理を実証しようとしている)。
あなたはただ一つの文を持つことができます。複数行の上に表現し、それが唯一の少ない不可欠、ほぼ正確にあなたのサンプルコードのように読み込みます:
boolean negativeValue
= defaultStock < 0
| defaultWholesale < 0
| defaultRetail < 0
| defaultDelivery < 0;
それは暗黙的にブランチを使用することを意味し、それが何倍も高価になることができ、比較をやって回避していてもので、最も簡単な式の場合、|
を使用すると、より高速な||
よりもすることができます。
それはあなたの問題のためにやり過ぎかもしれませんが、グアバ>ライブラリはPredicate
sでいくつかの素晴らしい構文を持っており、短絡の評価または/およびPredicate
sを行います。
は本質的に、比較は、オブジェクトになっコレクションにパッケージ化し、次いでにわたって反復されます。または述語、反復の最初の真のヒット戻り、またその逆のために及びます。
分離の概念は、テストロジックからデータをテストしました。コードサンプルます:
// declare data
DataType [] dataToTest = new DataType[] {
defaultStock,
defaultWholesale,
defaultRetail,
defaultDelivery
}
// define logic
boolean checkIfAnyNegative(DataType [] data) {
boolean negativeValue = false;
int i = 0;
while (!negativeValue && i < data.length) {
negativeValue = data[i++] < 0;
}
return negativeValue;
}
コードルックスより冗長と一目瞭然。あなたもこのように、メソッド呼び出しで配列を作成することがあります:
checkIfAnyNegative(new DataType[] {
defaultStock,
defaultWholesale,
defaultRetail,
defaultDelivery
});
これは、「比較文字列」より読みやすくだし、また、(配列の割り当てとメソッド呼び出しのコストで)短絡の性能上の利点を持っています。
の編集を さらに読みやすくするには、単に可変引数パラメータを使用することによって達成することができます:
メソッドのシグネチャは次のようになります。
boolean checkIfAnyNegative(DataType ... data)
そして、呼び出しはこのようになります:
checkIfAnyNegative( defaultStock, defaultWholesale, defaultRetail, defaultDelivery );
これは古い記事ですが、初心者のための異なる視点を提供するために、私は例を与えるたいと思います。
私は、同様の化合物を事業者のための最も一般的な使用例は+=
になると思います。
int a = 10; // a = 10
a += 5; // a = 15
これのポイントは何でしたか?ポイントは、定型を回避し、反復コードを排除することでした。
だから、次の行が同じ行に二度変数b1
を入力するために避け、正確に同じことをします。
b1 |= b2;
List<Integer> params = Arrays.asList (defaultStock, defaultWholesale,
defaultRetail, defaultDelivery);
int minParam = Collections.min (params);
negativeValue = minParam < 0;
||論理ブールOR
|ビット単位のOR
| =ビット単位の包含的ORと代入演算子
理由|それはビットごとのOR論理和はしませんので、= shortcircitがありません。 それは言うことです。
C |= 2 is same as C = C | 2