87

したがって、ブール値の二項演算子の場合、Javaには、、、、および&があります。|^&&||

ここで彼らが何をしているのかを簡単に要約しましょう:

の場合&、結果の値はtrue、両方のオペランド値がtrue;の場合です。それ以外の場合、結果はfalseです。

の場合|、結果の値はfalse、両方のオペランド値がfalse;の場合です。それ以外の場合、結果はtrueです。

の場合^、結果の値はtrue、オペランド値が異なる場合です。それ以外の場合、結果はfalseです。

&&演算子は似&ていますが、左側のオペランドの値が。の場合にのみ右側のオペランドを評価しますtrue

||演算子はに似|ていますが、左側のオペランドの値が。の場合にのみ右側のオペランドを評価しますfalse

現在、5つすべてのうち、3つには複合代入バージョン、つまり、、|=およびが&=あり^=ます。だから私の質問は明白です:なぜJavaは同様に提供&&=しないのですか?||=必要以上に必要だと思い&=ます|=

そして、Javaにはがありますので、「長すぎるため」は良い答えではないと思います>>>=。この省略にはもっと良い理由があるに違いありません。


15.26代入演算子から:

12個の代入演算子があります。[...]= *= /= %= += -= <<= >>= >>>= &= ^= |=


&&=||=が実装された場合、最初に右側を評価しないのはそれだけであるというコメントがありました。複合代入演算子が最初に右側を評価するというこの概念は誤りだと思います。

15.26.2複合代入演算子から:

フォームの複合代入式は、E1 op= E2と同等ですE1 = (T)((E1) op (E2))。ここTで、はのタイプですが、 1回だけ評価されるE1点が異なります。E1

NullPointerException証拠として、次のスニペットは、ではなく、をスローしArrayIndexOutOfBoundsExceptionます。

    int[] a = null;
    int[] b = {};
    a[0] += b[-1];
4

11 に答える 11

30

理由

ほとんどの開発者にとってこれらの演算子は次のとおりであるため、演算子&&=と演算子はJava では||=使用できません。

  • エラーを起こしやすい
  • 使い物にならない

&&=

Java が&&=演算子を許可している場合、そのコードは次のとおりです。

bool isOk = true; //becomes false when at least a function returns false
isOK &&= f1();
isOK &&= f2(); //we may expect f2() is called whatever the f1() returned value

次と同等です。

bool isOk = true;
if (isOK) isOk = f1();
if (isOK) isOk = f2(); //f2() is called only when f1() returns true

この最初のコードは、多くの開発者がf1() の戻り値が常に呼び出されると考えているため、エラーが発生しやすくなっています。whereが返されたときにのみ呼び出されるf2()ようなものです。bool isOk = f1() && f2();f2()f1()true

開発者が return の場合にf2()のみ呼び出されるようにしたい場合は、上記の 2 番目のコードの方がエラーが発生しにくくなりますf1()true

開発者は常に呼び出されることを&=望んでいるため、Elseで十分です。f2()

同じ例ですが、&=

bool isOk = true;
isOK &= f1();
isOK &= f2(); //f2() always called whatever the f1() returned value

さらに、JVM は上記のコードを次のように実行する必要があります。

bool isOk = true;
if (!f1())  isOk = false;
if (!f2())  isOk = false;  //f2() always called

比較&&&結果

ブール値に適用した場合、演算子の結果は&&同じですか?&

次の Java コードを使用して確認してみましょう。

public class qalcdo {

    public static void main (String[] args) {
        test (true,  true);
        test (true,  false);
        test (false, false);
        test (false, true);
    }

    private static void test (boolean a, boolean b) {
        System.out.println (counter++ +  ") a=" + a + " and b=" + b);
        System.out.println ("a && b = " + (a && b));
        System.out.println ("a & b = "  + (a & b));
        System.out.println ("======================");
    }

    private static int counter = 1;
}

出力:

1) a=true and b=true
a && b = true
a & b = true
======================
2) a=true and b=false
a && b = false
a & b = false
======================
3) a=false and b=false
a && b = false
a & b = false
======================
4) a=false and b=true
a && b = false
a & b = false
======================

したがって、はい&&、ブール値を置き換えることができ&ます;-)

&=の代わりに使用することをお勧めし&&=ます。

同じ||=

と同じ理由&&=:
operator|=は よりもエラーが発生しにくい||=

開発者が return のときに呼び出されたくf2()ない場合は、次の代替案をお勧めしますf1()true

// here a comment is required to explain that 
// f2() is not called when f1() returns false, and so on...
bool isOk = f1() || f2() || f3() || f4();

また:

// here the following comments are not required 
// (the code is enough understandable)
bool isOk = false;
if (!isOK) isOk = f1();
if (!isOK) isOk = f2(); //f2() is not called when f1() returns false
if (!isOK) isOk = f3(); //f3() is not called when f1() or f2() return false
if (!isOK) isOk = f4(); //f4() is not called when ...
于 2012-03-29T15:30:09.490 に答える
17

おそらく、次のような理由で

x = false;
x &&= someComplexExpression();

に割り当ててx評価する必要があるように見えますsomeComplexExpression()が、評価が の値に依存しているという事実はx、構文からは明らかではありません。

また、Java の構文は C に基づいているため、これらの演算子を追加する差し迫った必要性を誰も認識していませんでした。とにかく、if ステートメントを使用したほうがよいでしょう。

于 2010-02-24T08:33:31.823 に答える
12

C でこのようになっているので、Java でこのようになっています。

C でなぜそうなのかという疑問は、& と && が異なる演算子になったとき (C が B から派生する前に)、&= のさまざまな演算子が単純に見落とされたためです。

しかし、私の回答の 2 番目の部分には、それを裏付ける情報源がありません。

于 2009-10-01T17:39:22.773 に答える
7

主な理由は、Java 構文が C (または少なくとも C ファミリ) に基づいており、C ではこれらすべての代入演算子が単一のレジスタで算術またはビット単位のアセンブリ命令にコンパイルされるためです。代入演算子バージョンは一時的なものを回避し、初期の非最適化コンパイラでより効率的なコードを生成した可能性があります。論理演算子 (C で呼ばれている) に相当するもの (&&=および||=) は、単一のアセンブリ命令とは明確に対応していません。それらは通常、命令のテストおよび分岐シーケンスに展開されます。

興味深いことに、Ruby のような言語に||= と &&= があります。

編集:JavaとCでは用語が異なります

于 2010-02-24T08:31:06.897 に答える
4

Java の本来の目的の 1 つは、「単純で、オブジェクト指向で、親しみやすい」ことでした。この場合に適用されるように、&= はよく知られています (C、C++ にはそれがあり、このコンテキストでよく知られているということは、これら 2 つを知っている人にとってはなじみ深いという意味です)。

&&= は馴染みがなく、言語設計者が言語に追加できるすべての演算子を考えているわけではないという意味で単純ではありません。

于 2009-10-01T17:59:54.783 に答える
3

ブール変数の場合、&& および || & と | の間、短絡評価を使用します。そうしないと、&&= と ||= も短絡評価を使用することが予想されます。これには良い使用例があります。特に、ループを繰り返し処理する場合は、高速、効率的、簡潔にする必要があります。

書く代わりに

foreach(item in coll)
{
   bVal = bVal || fn(item); // not so elegant
}

書きたい

foreach(item in coll)
{
  bVal ||= fn(item);    // elegant
}

また、bVal が true になると、残りの繰り返しで fn() が呼び出されないことがわかります。

于 2013-02-21T16:03:56.583 に答える
2

' &' と ' &&' は ' ' と同じ&&ではありません。最初のオペランドが false の場合は実行されませんが、' &' はとにかく実行されます (数値とブール値の両方で機能します)。

存在するほうが理にかなっていることには同意しますが、存在しなくてもそれほど悪くはありません。Cにはなかったので、そこにはなかったと思います。

本当に理由が思いつきません。

于 2009-10-01T17:50:24.123 に答える
0

&

両方のオペランドを検証します。これはビット単位の演算子です。Java では、整数型 long、int、short、char、および byte に適用できるいくつかのビット演算子が定義されています。

&&

結果が false になるため、最初のオペランドが false に評価されると評価を停止します。これは論理演算子です。ブール値に適用できます。

&& 演算子は & 演算子に似ていますが、コードをより効率的にすることができます。式全体が true になるには、& 演算子によって比較される両方の式が true でなければならないため、最初の式が false を返す場合に 2 番目の式を評価する理由はありません。& 演算子は常に両方の式を評価します。&& 演算子は、最初の式が true の場合にのみ 2 番目の式を評価します。

&&= 代入演算子を使用しても、言語に新しい機能が実際に追加されることはありません。ビット単位の演算子の算術演算はより表現力があり、ブール演算を含む整数のビット単位の算術演算を行うことができます。論理演算子は、ブール演算のみを実行できます。

于 2015-06-12T13:20:56.353 に答える
0

Rubyでは許可されています。

推測すると、あまり使われていないので実装されていませんでした。別の説明としては、パーサーが = の前の文字だけを見るということです。

于 2009-10-01T17:39:55.377 に答える
0

「信じられないほど醜く見える!」以上の理由は考えられません。

于 2009-10-01T17:40:14.080 に答える