Приоритет операций в Java
Приоритет операций определяет, в каком порядке Java вычисляет операторы внутри одного выражения. Как и в математике, умножение и деление выполняются раньше сложения и вычитания: в выражении 5 + 3 * 2 сначала вычисляется 3 * 2. Наивысший приоритет имеют разделители — круглые скобки, индексы массивов и оператор доступа ., за ними идут унарные операции, а оператор присваивания замыкает список с самым низким приоритетом.
Таблица приоритетов операций в Java
Операторы Java делятся на несколько групп: арифметические, операторы сравнения, логические, побитовые и операторы присваивания. В таблице ниже они расположены по убыванию приоритета: уровень 1 вычисляется первым, уровень 15 — последним. Операторы одной строки имеют одинаковый приоритет.
| Уровень | Операторы | Категория |
|---|---|---|
| 1 | [ ] ( ) . | Разделители: индекс массива, скобки, доступ к члену класса |
| 2 | ++ -- ~ ! + (унарный) - (унарный) (приведение типов) | Унарные операции |
| 3 | * / % | Умножение, деление, остаток |
| 4 | + - | Сложение (и конкатенация строк), вычитание |
| 5 | >> >>> << | Битовые сдвиги |
| 6 | > >= < <= instanceof | Сравнения и проверка типа |
| 7 | == != | Равенство и неравенство |
| 8 | & | Побитовое И (для boolean — логическое И без короткого замыкания) |
| 9 | ^ | Побитовое исключающее ИЛИ |
| 10 | | | Побитовое ИЛИ (для boolean — логическое ИЛИ без короткого замыкания) |
| 11 | && | Логическое И (с коротким замыканием) |
| 12 | || | Логическое ИЛИ (с коротким замыканием) |
| 13 | ? : | Тернарный (условный) оператор |
| 14 | -> | Лямбда-выражение (условно, см. пояснение ниже) |
| 15 | = (и составные: +=, -=, *= и другие) | Присваивание |
Одно уточнение к строке 14: стрелка -> в лямбда-выражении — не оператор в терминах спецификации Java (JLS), и официальная таблица приоритетов Oracle её не включает. Здесь она приведена условно — как конструкция с очень низким приоритетом: лямбда «захватывает» всё выражение справа от стрелки, уступая только присваиванию.
Важно
Строка 2 объединяет унарные операции для простоты. Формально по JLS постфиксные x++ и x-- стоят чуть выше по приоритету, чем префиксные ++x, --x, унарные +/-, ~, ! и приведение типов. Это упрощение, а не ошибка: на практике различие проявляется крайне редко, но на собеседовании о нём полезно знать.
Ассоциативность: равный приоритет
Когда в выражении подряд стоят операторы одного уровня приоритета, порядок определяет ассоциативность. Большинство бинарных операторов Java левоассоциативны — вычисляются слева направо:
int d = 100 - 10 - 5; // лево: (100 - 10) - 5 = 85, а не 100 - (10 - 5) = 95 Правоассоциативны присваивание = (включая составные операторы), тернарный оператор ? : и унарные операции — они группируются справа налево:
int x, y, z;
x = y = z = 10; // право: x = (y = (z = 10)) - все три переменные равны 10 Подробно порядок вычисления таких цепочек разобран в уроке об операторе присваивания.
Примеры: как приоритет меняет результат
Начнём с арифметики — два внешне похожих выражения дают разные результаты:
int a = 5 + 3 * 2; // результат: 11, так как умножение выполняется первым
int b = (5 + 3) * 2; // результат: 16, так как сложение выполняется первым из-за скобок Как видно из примера, круглые скобки позволяют изменить порядок выполнения операций — и существенно повлиять на итог.
Логические операторы тоже подчиняются приоритету: && выполняется раньше, чем ||. Сравнения (уровень 6) выше обоих, поэтому скобки вокруг них не обязательны, но с ними выражение читается легче:
boolean result = (5 > 3) && (10 > 8); // true, так как оба условия верны
boolean result2 = (5 > 3) || (10 < 8); // true, так как одно из условий верно
boolean r = true || false && false; // true: сначала false && false, затем true || false На чём чаще всего ошибаются — смешение &, ^ и | без скобок. Их приоритеты различаются (& выше ^, а ^ выше |), и результат может не совпасть с ожиданием:
boolean p = true, q = false, s = false;
boolean r1 = p | q & s; // & выше |: вычисляется p | (q & s) = true | false = true
boolean r2 = (p | q) & s; // со скобками: (true | false) & false = false Без скобок выражение p | q & s истинно, а со скобками (p | q) & s — ложно, хотя переменные те же.
Совет
Таблицу приоритетов не нужно заучивать — это справочник-шпаргалка. Достаточно помнить общую логику (разделители и унарные — вверху, присваивание — внизу, арифметика раньше сравнений, сравнения раньше логики), а в неочевидных местах ставить явные скобки: компилятору они не мешают, а читателю кода сразу показывают ваш замысел.
Часто задаваемые вопросы
Какие операции имеют самый высокий и самый низкий приоритет в Java?
Наивысший приоритет у разделителей — круглых скобок, индексов массива [ ] и оператора доступа к члену класса ., сразу за ними идут унарные операции (++, --, !, ~, унарные +/-, приведение типов). Самый низкий приоритет — у оператора присваивания = и его составных форм: они выполняются последними, когда правая часть уже вычислена.
Что выполняется раньше: && или ||?
Оператор && имеет более высокий приоритет, чем ||. Поэтому выражение a || b && c вычисляется как a || (b && c), а не как (a || b) && c. Если нужен другой порядок — ставьте скобки; они же делают выражение понятнее даже там, где приоритет и так на вашей стороне.
Что такое ассоциативность и чем она отличается от приоритета?
Приоритет решает, какой из разных операторов вычислять первым, а ассоциативность — в каком порядке выполнять операторы одного уровня, стоящие подряд. Большинство бинарных операторов Java левоассоциативны (100 - 10 - 5 означает (100 - 10) - 5), а присваивание, тернарный оператор и унарные операции правоассоциативны (x = y = 10 означает x = (y = 10)).
Нужно ли заучивать таблицу приоритетов операторов?
Нет. Достаточно помнить общую схему: разделители и унарные операции — наверху, затем арифметика, сравнения, логические операторы, и в самом низу присваивание. Во всех неочевидных случаях (особенно при смешении &, ^, | или битовых сдвигов с арифметикой) профессиональный код использует явные скобки — это надёжнее памяти и понятнее коллегам.
Презентацию с видео можно скачать на Patreon.
Видео объяснение
Предпочитаете видеоформат? Посмотрите этот урок с примерами и объяснениями.
Комментарии