1. 概要

Javaは、ビット演算子のセットを提供します。 これらの演算子を使用すると、数値の個々のビットを簡単に操作できます。

ただし、ビット演算の結果を比較すると、一般的な落とし穴に陥る可能性があります。

このクイックチュートリアルでは、Javaコンパイル時エラー「二項演算子の不正なオペランドタイプ」が発生する理由と、問題を解決する方法について説明します。

2. 問題の紹介

いつものように、例を通して問題を理解します。 しかし、最初に、簡単な方法を見てみましょう。

public void checkNumber() {
    List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
    intList.forEach(i -> {
        if (i & 1 == 1) {
            System.out.println(i + " is odd.");
        } else {
            System.out.println(i + " is even.");
        }
    });
}

ご覧のとおり、 checkNumber メソッドは、 intList をウォークスルーし、各数値が偶数か奇数かをチェックして出力します。

メソッドの奇数チェックロジックは、一般的な方法で実装されていないことに注意してください: i%2 ==1。 その代わり、 整数(i)と1に対してビット単位のAND(&)演算を実行します。 結果が1の場合、整数がわかります奇数です: i&1 == 1

ただし、上記のメソッドをテストしようとすると、驚くべきことにコードはコンパイルされません。

java: bad operand types for binary operator '&'
  first type:  java.lang.Integer
  second type: boolean

次に、問題の原因とその解決方法を理解しましょう。

3. Java演算子の優先順位を理解する

まず第一に、エラーメッセージは非常に単純です。 booleanタイプとIntegerタイプでビット単位のANDを実行しようとしていることを示しています。

しかし、私たちが文字通り「 i&1 コード内の」。 コンパイラがboolean型がビット単位のAND演算に関与していると考えるのはなぜですか?

それの訳は 「==」演算子は「&」演算子よりも優先されます。 つまり、「 i&1 == 1 」は「」と同じです i&(1 == 1) 「。 したがって、「 i&true(ブール値) 「。

ここで、次のように尋ねることができます。 。 しかし、なぜ’ i%2 == 1 ‘が期待どおりに機能するのでしょうか?」

その質問に答えるには、Java演算子の優先順位規則を詳しく調べる必要があります。

Javaはかなりの数の演算子を提供してきました。 実際には、さまざまな演算子を一緒に使用することがよくあります。 したがって、Java演算子の優先順位を理解することが不可欠です。 そうしないと、予期しない結果が生じる可能性があります。

次に、Java演算子の優先順位ルールを見てみましょう(テーブルの上位にある演算子が表示されるほど、優先順位が高くなります)。

オペレーター 優先順位
後置 expr ++ expr
単項 ++ expr expr + expr expr 〜!
乗法 * / %
添加剤 + –
シフト << >> >>>
関連した <> <=> = instanceof
平等 ==!=
ビットごとのAND &
ビット単位の排他的論理和 ^
ビット単位の包括的OR |
論理積 &&
論理和 ||
三元 ? :
割り当て = + =-= * = / =%=&= ^ = | = << = >> = >>> =

上記のリストからわかるように、モジュロ演算子(%)は、等式演算子(==)よりも優先されます。 一方で、 ビットごとのAND演算子(&)が等号演算子(==)の下にありますテーブルで。

それが理由です “ i%2 == 1 」は期待どおりに機能しますが、「 i&1 == 1 ” ではない。

この例では、コンパイル時エラーが発生しました。 したがって、問題を比較的早期に検出できます。 ただし、演算子の優先順位のバグがコンパイルされても、間違った結果が生成される実装を想像してみてください。 問題の本当の原因を見つけるには、不必要に多くの時間がかかる可能性があります。

したがって、Java演算子の優先順位規則を覚えておく価値があります。

4. 問題の修正

問題の原因がわかったので、問題の修正は難しい作業ではありません。 ビット単位のAND演算に括弧を追加する必要があります。

if (i & 1 == 1)  -->  if ((i & 1) == 1)

修正後、メソッドをもう一度実行すると、コンパイラーが文句を言わなくなったことがわかり、期待どおりの出力が得られます。

1 is odd.
2 is even.
3 is odd.
4 is even.
5 is odd.
6 is even.
7 is odd.

5. 結論

この簡単な記事では、ビット単位のAND演算の例を通じて、コンパイルエラー「二項演算子の不正なオペランドタイプ」を分析しました。

さらに、Java演算子の優先順位規則についても説明しました。

最後に、問題を修正しました。