Перейти к основному содержимому

Ошибка Java «неверные типы операндов для бинарного оператора»

· 4 мин. чтения

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. Если результат равен 1, мы знаем, что целое число i является нечетным числом: i & 1 ==1 .

Однако, когда мы пытаемся протестировать описанный выше метод, код неожиданно не компилируется:

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

Далее давайте разберемся, в чем причина проблемы и как ее решить.

3. Понимание приоритета операторов Java

Во-первых, сообщение об ошибке довольно простое. В нем говорится, что мы пытаемся выполнить побитовое И для логического типа и целочисленного типа.

Однако это странно, поскольку мы буквально написали « i & 1 » в коде. Почему компилятор считает, что логический тип участвует в побитовой операции И?

Это связано с тем, что оператор « == » имеет более высокий приоритет, чем оператор « & ». То есть выражение « i & 1 == 1 » такое же, как « i & (1 == 1) ». Таким образом, у нас есть « i & true (boolean) ».

Теперь мы можем спросить: «Хорошо, == имеет более высокий приоритет, чем & . Но почему ' i % 2 == 1 ' работает так, как ожидалось?»

Чтобы ответить на этот вопрос, нам нужно более подробно рассмотреть правило приоритета операторов Java.

Java предоставляет довольно много операторов . На практике мы часто используем разные операторы вместе. Поэтому важно понимать приоритет операторов Java. В противном случае мы можем получить неожиданный результат.

Далее, давайте посмотрим на правило приоритета операторов Java (чем выше в таблице стоит оператор, тем выше его приоритет):

   | Операторы    | Приоритет   | 
| постфикс | `выражение ++ выражение —` |
| унарный | `++ выражение — выражение + выражение — выражение ~ !` |
| мультипликативный | `* / %` |
| добавка | `+ –` |
| сдвиг | `<< >> >>>` |
| относительный | `< > <= >= instanceof` |
| равенство | `== !=` |
| побитовое И | `&` |
| побитовое исключающее ИЛИ | `^` |
| побитовое включительно ИЛИ | `|` |
| логическое И | `&&` |
| логическое ИЛИ | `||` |
| троичный | `? :` |
| назначение | `= += -= *= /= %= &= ^= |= <<= >>= >>>=` |

Как видно из приведенного выше списка, оператор по модулю (%) имеет более высокий приоритет, чем оператор равенства ( == ) . С другой стороны, побитовый оператор И (&) находится ниже оператора равенства (==) в таблице.

Вот почему « i % 2 == 1 » работает, как и ожидалось, а « i & 1 == 1 » — нет.

В нашем примере мы столкнулись с ошибкой времени компиляции. Таким образом, мы можем обнаружить проблему относительно рано. Однако представьте, что некоторая реализация с ошибкой приоритета оператора компилируется, но выдает неверный результат. Поиск реальной причины проблемы может занять у нас много времени.

Итак, стоит помнить о правиле приоритета операторов Java.

4. Решение проблемы

Теперь, когда мы понимаем причину проблемы, ее устранение не является сложной задачей. Нам просто нужно добавить круглые скобки к операции побитового И:

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. Вывод

В этой быстрой статье мы проанализировали ошибку компиляции «неправильные типы операндов для бинарного оператора» на примере операции побитового И.

Кроме того, мы обсудили правило приоритета операторов Java.

Наконец, мы исправили проблему.