HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-21
1 <p><a>#База знаний</a></p>
1 <p><a>#База знаний</a></p>
2 <ul><li>11 мар 2021</li>
2 <ul><li>11 мар 2021</li>
3 <li>0</li>
3 <li>0</li>
4 </ul><p>Что за операторы такие, зачем им префиксная и постфиксная формы, и как вычислять сложные выражения с ними (пригодится на экзамене и собеседовании).</p>
4 </ul><p>Что за операторы такие, зачем им префиксная и постфиксная формы, и как вычислять сложные выражения с ними (пригодится на экзамене и собеседовании).</p>
5 <p>Программист, преподаватель Skillbox. Пишет про Java. </p>
5 <p>Программист, преподаватель Skillbox. Пишет про Java. </p>
6 <p>В программировании часто приходится выполнять операции (вычислять результат выражений), в которых переменная должна увеличиться или уменьшиться на единицу.</p>
6 <p>В программировании часто приходится выполнять операции (вычислять результат выражений), в которых переменная должна увеличиться или уменьшиться на единицу.</p>
7 <p>Для этого придуманы унарные операторы ++ и --. С ними код короче и писать его быстрее.</p>
7 <p>Для этого придуманы унарные операторы ++ и --. С ними код короче и писать его быстрее.</p>
8 <p>Оператор (++) называется инкремент. Он увеличивает значение целочисленной переменной на единицу.</p>
8 <p>Оператор (++) называется инкремент. Он увеличивает значение целочисленной переменной на единицу.</p>
9 <p>Обратный оператор (--) зовётся декремент. Он значение переменной на один уменьшает.</p>
9 <p>Обратный оператор (--) зовётся декремент. Он значение переменной на один уменьшает.</p>
10 int x = 3, у = 3; x++; // инкрементируем x у--; // декрементируем y System.out.println("x = " + x + ", y = " + y); --OUTPUT&gt; x = 4, y = 2<p>Тут всё просто, достаточно удостовериться, что значения переменных поменялись.</p>
10 int x = 3, у = 3; x++; // инкрементируем x у--; // декрементируем y System.out.println("x = " + x + ", y = " + y); --OUTPUT&gt; x = 4, y = 2<p>Тут всё просто, достаточно удостовериться, что значения переменных поменялись.</p>
11 <p><strong>Примечание.</strong>Инкремент и декремент относятся к арифметическим операторам. Мы помним, что операнды арифметических операторов должны быть числового типа. Однако в Java допустим и тип char, потому что здесь это по сути разновидность типа int.</p>
11 <p><strong>Примечание.</strong>Инкремент и декремент относятся к арифметическим операторам. Мы помним, что операнды арифметических операторов должны быть числового типа. Однако в Java допустим и тип char, потому что здесь это по сути разновидность типа int.</p>
12 <p>Проверим, как это работает с инкрементом и декрементом.</p>
12 <p>Проверим, как это работает с инкрементом и декрементом.</p>
13 char x = 'b', y = 'c'; x++; // инкрементируем x y--; // декрементируем y System.out.println("x = " + x); System.out.println("y = " + y); --OUTPUT&gt; x = c y = b<p>Работает: инкремент помещает в символьную переменную следующий знак из кодировки ASCII, а декремент - предыдущий.</p>
13 char x = 'b', y = 'c'; x++; // инкрементируем x y--; // декрементируем y System.out.println("x = " + x); System.out.println("y = " + y); --OUTPUT&gt; x = c y = b<p>Работает: инкремент помещает в символьную переменную следующий знак из кодировки ASCII, а декремент - предыдущий.</p>
14 for (int i = 0; i &lt; 3; i++) { System.out.println(i); } --OUTPUT&gt; 0 1 2<p>На каждой итерации цикла значение переменной i выводится в консоль, а сама переменная увеличивается на один после каждого витка.</p>
14 for (int i = 0; i &lt; 3; i++) { System.out.println(i); } --OUTPUT&gt; 0 1 2<p>На каждой итерации цикла значение переменной i выводится в консоль, а сама переменная увеличивается на один после каждого витка.</p>
15 <p><strong>Примечание:</strong>если в примере выше заменить i++ на ++i, то результат в консоли не поменяется - проверьте.</p>
15 <p><strong>Примечание:</strong>если в примере выше заменить i++ на ++i, то результат в консоли не поменяется - проверьте.</p>
16 <p>Почему?</p>
16 <p>Почему?</p>
17 <p>Дело в том, что преинкремент и постинкремент в условии цикла for можно сравнить с вызовом двух разных функций. Каждая из них делает одно и то же - увеличивает переменную i (после выполнения тела цикла), и только возвращаемые ими значения различаются.</p>
17 <p>Дело в том, что преинкремент и постинкремент в условии цикла for можно сравнить с вызовом двух разных функций. Каждая из них делает одно и то же - увеличивает переменную i (после выполнения тела цикла), и только возвращаемые ими значения различаются.</p>
18 <p>Однако возвращаемое инкрементом значение в условии цикла использовать негде (нет выражения для вычисления) - поэтому оно просто выбрасывается.</p>
18 <p>Однако возвращаемое инкрементом значение в условии цикла использовать негде (нет выражения для вычисления) - поэтому оно просто выбрасывается.</p>
19 <p>Вот почему на работе цикла подобная замена не отразилась.</p>
19 <p>Вот почему на работе цикла подобная замена не отразилась.</p>
20 <p>Перепишем пример с циклом так:</p>
20 <p>Перепишем пример с циклом так:</p>
21 for (int i = 0; i &lt; 3;) { System.out.println(i++); } --OUTPUT&gt; 0 1 2<p>Как видим, вывод снова не изменился.</p>
21 for (int i = 0; i &lt; 3;) { System.out.println(i++); } --OUTPUT&gt; 0 1 2<p>Как видим, вывод снова не изменился.</p>
22 <p>Всё потому, что в метод System.<em>out</em>.println () передаётся текущее значение переменной i, и лишь потом оно увеличивается на единицу.</p>
22 <p>Всё потому, что в метод System.<em>out</em>.println () передаётся текущее значение переменной i, и лишь потом оно увеличивается на единицу.</p>
23 <p>За это отвечает постфиксная форма записи инкремента. А ещё есть префиксная. И для декремента тоже.</p>
23 <p>За это отвечает постфиксная форма записи инкремента. А ещё есть префиксная. И для декремента тоже.</p>
24 <p>Синтаксис тут такой (x - переменная):</p>
24 <p>Синтаксис тут такой (x - переменная):</p>
25 <strong>Операция</strong><strong>Постфиксная версия</strong><strong>Префиксная версия</strong>Инкремент x++ ++x Декремент х-- --х<ul><li>Префиксные операторы ++x (--x) записывают в переменную x изменённое значение и его же возвращают вместо себя (в исходное выражение).</li>
25 <strong>Операция</strong><strong>Постфиксная версия</strong><strong>Префиксная версия</strong>Инкремент x++ ++x Декремент х-- --х<ul><li>Префиксные операторы ++x (--x) записывают в переменную x изменённое значение и его же возвращают вместо себя (в исходное выражение).</li>
26 <li>Постфиксные операторы x++ (x--) возвращают вместо себя текущее значение переменной х, а потом записывают в x новое значение.</li>
26 <li>Постфиксные операторы x++ (x--) возвращают вместо себя текущее значение переменной х, а потом записывают в x новое значение.</li>
27 </ul><p>Обратите внимание на слово<strong>потом</strong>. Потом - это когда? После вычисления всего выражения? Чтобы понять это, разберёмся с порядком вычисления инкрементов и декрементов.</p>
27 </ul><p>Обратите внимание на слово<strong>потом</strong>. Потом - это когда? После вычисления всего выражения? Чтобы понять это, разберёмся с порядком вычисления инкрементов и декрементов.</p>
28 <p>Значения, которые инкременты возвращают в выражение, вычисляются до выполнения других операций. И то же самое для декрементов.</p>
28 <p>Значения, которые инкременты возвращают в выражение, вычисляются до выполнения других операций. И то же самое для декрементов.</p>
29 <p>То есть у операторов ++ и -- наивысший приоритет при вычислении результата выражения.</p>
29 <p>То есть у операторов ++ и -- наивысший приоритет при вычислении результата выражения.</p>
30 <p>Не путайте<em>приоритет</em>с обычным порядком выполнения операторов. Все инструкции Java выполняет в привычном нам направлении (слева направо), и операнды операторов вычисляет так же.</p>
30 <p>Не путайте<em>приоритет</em>с обычным порядком выполнения операторов. Все инструкции Java выполняет в привычном нам направлении (слева направо), и операнды операторов вычисляет так же.</p>
31 <p>Все арифметические операторы (за исключением унарных + и -; преинкремента ++x и предекремента --x) -<em>левоассоциативны</em>, то есть выполняются слева направо.</p>
31 <p>Все арифметические операторы (за исключением унарных + и -; преинкремента ++x и предекремента --x) -<em>левоассоциативны</em>, то есть выполняются слева направо.</p>
32 <p><em>Приоритеты</em>же определяют порядок выполнения операторов, которые сами являются частью более сложного (составного) арифметического или логического выражения.</p>
32 <p><em>Приоритеты</em>же определяют порядок выполнения операторов, которые сами являются частью более сложного (составного) арифметического или логического выражения.</p>
33 <p>Если на одном уровне встречаются операции одинакового<em>приоритета</em>, то какие из них выполнять первыми - определяет уже<em>ассоциативность</em>.</p>
33 <p>Если на одном уровне встречаются операции одинакового<em>приоритета</em>, то какие из них выполнять первыми - определяет уже<em>ассоциативность</em>.</p>
34 int x = 3; int y = 3; int a = 2 * x++; // здесь значение a равно 6, а x равен 4 int b = 2 * --y; // здесь значение b равно 4, а y равен 2 System.out.println(a); System.out.println(b); System.out.println(x); System.out.println(y); --OUTPUT&gt; 6 4 4 2<p>Разберём пример выше.</p>
34 int x = 3; int y = 3; int a = 2 * x++; // здесь значение a равно 6, а x равен 4 int b = 2 * --y; // здесь значение b равно 4, а y равен 2 System.out.println(a); System.out.println(b); System.out.println(x); System.out.println(y); --OUTPUT&gt; 6 4 4 2<p>Разберём пример выше.</p>
35 <p><strong>x = 3.</strong>Найдём значение выражения 2 * x++:</p>
35 <p><strong>x = 3.</strong>Найдём значение выражения 2 * x++:</p>
36 <ul><li>Сперва вычисляем постинкремент x++, он возвращает в выражение текущее значение x, то есть 3, а потом увеличивает x на 1.</li>
36 <ul><li>Сперва вычисляем постинкремент x++, он возвращает в выражение текущее значение x, то есть 3, а потом увеличивает x на 1.</li>
37 <li>Это эквивалентно исполнению кода: a = 2 * x; x = x + 1;</li>
37 <li>Это эквивалентно исполнению кода: a = 2 * x; x = x + 1;</li>
38 <li>Значение a стало равняться 6, а x равен 4.</li>
38 <li>Значение a стало равняться 6, а x равен 4.</li>
39 </ul><p><strong>y = 3.</strong>Вычислим значение выражения 2 * --y:</p>
39 </ul><p><strong>y = 3.</strong>Вычислим значение выражения 2 * --y:</p>
40 <ul><li>Сперва вычисляем предекремент --y, он уменьшает y на 1 и возвращает вместо себя это новое значение.</li>
40 <ul><li>Сперва вычисляем предекремент --y, он уменьшает y на 1 и возвращает вместо себя это новое значение.</li>
41 <li>Это эквивалентно исполнению кода: y = y - 1; b = 2 * y;</li>
41 <li>Это эквивалентно исполнению кода: y = y - 1; b = 2 * y;</li>
42 </ul><p>Значение b стало равным 4, а y равен 2.</p>
42 </ul><p>Значение b стало равным 4, а y равен 2.</p>
43 <p>Если декременты или инкременты разделены каким-нибудь бинарным оператором (вроде +, -, *, /), то ассоциативностью они уже не связаны (так как приоритет бинарного оператора заведомо ниже). И тогда мы вычисляем значение выражения традиционным методом - слева направо, учитывая приоритет операций Java.</p>
43 <p>Если декременты или инкременты разделены каким-нибудь бинарным оператором (вроде +, -, *, /), то ассоциативностью они уже не связаны (так как приоритет бинарного оператора заведомо ниже). И тогда мы вычисляем значение выражения традиционным методом - слева направо, учитывая приоритет операций Java.</p>
44 <p>В этом случае стоит помнить, что:</p>
44 <p>В этом случае стоит помнить, что:</p>
45 <ul><li>раньше всегда вычисляется декремент или инкремент, который стоит левее;</li>
45 <ul><li>раньше всегда вычисляется декремент или инкремент, который стоит левее;</li>
46 <li>скобки на порядок вычисления инкрементов и декрементов не влияют;</li>
46 <li>скобки на порядок вычисления инкрементов и декрементов не влияют;</li>
47 <li>конструкции типа ++x-- (--x++, ++x++ или --x--) запрещены.</li>
47 <li>конструкции типа ++x-- (--x++, ++x++ или --x--) запрещены.</li>
48 </ul><p><strong>Если в выражении много инкрементов/декрементов одной переменной</strong></p>
48 </ul><p><strong>Если в выражении много инкрементов/декрементов одной переменной</strong></p>
49 <p>Тогда входным значением переменной для вычисления каждого последующего инкремента или декремента будет значение этой переменной после вычисления предыдущего инкремента или декремента.</p>
49 <p>Тогда входным значением переменной для вычисления каждого последующего инкремента или декремента будет значение этой переменной после вычисления предыдущего инкремента или декремента.</p>
50 <p>То есть инкременты/декременты в выражении обрабатываются не одновременно, а по очереди, порядок в которой определяется ассоциативностью и приоритетом этих операторов в Java.</p>
50 <p>То есть инкременты/декременты в выражении обрабатываются не одновременно, а по очереди, порядок в которой определяется ассоциативностью и приоритетом этих операторов в Java.</p>
51 <p>Рассмотрим это на примере.</p>
51 <p>Рассмотрим это на примере.</p>
52 int x = 5; int y = ++x + x--; System.out.println("x = " + x); System.out.println("y = " + y); --OUTPUT&gt; 5 12<p><strong>Как думаете, почему значения такие?</strong></p>
52 int x = 5; int y = ++x + x--; System.out.println("x = " + x); System.out.println("y = " + y); --OUTPUT&gt; 5 12<p><strong>Как думаете, почему значения такие?</strong></p>
53 <p>Разберём пример выше.</p>
53 <p>Разберём пример выше.</p>
54 <p><strong>x = 5.</strong>Начинаем вычислять выражение ++x + x--:</p>
54 <p><strong>x = 5.</strong>Начинаем вычислять выражение ++x + x--:</p>
55 <ul><li>Двигаемся слева направо до первого инкремента/декремента. У нас это ++x (преинкремент x). Мы помним, что он увеличивает x на 1 и сразу возвращает вместо себя это новое значение x (5 + 1 = 6).</li>
55 <ul><li>Двигаемся слева направо до первого инкремента/декремента. У нас это ++x (преинкремент x). Мы помним, что он увеличивает x на 1 и сразу возвращает вместо себя это новое значение x (5 + 1 = 6).</li>
56 <li>Подставляем 6 в наше выражение вместо ++x: y = 6 + x--.</li>
56 <li>Подставляем 6 в наше выражение вместо ++x: y = 6 + x--.</li>
57 <li>Вновь двигаемся слева направо до первого инкремента/декремента.</li>
57 <li>Вновь двигаемся слева направо до первого инкремента/декремента.</li>
58 <li>Встречаем x-- (постдекремент x). Вспоминаем, что он возвращает вместо себя текущее значение x (которое у нас после инкремента равно 6).</li>
58 <li>Встречаем x-- (постдекремент x). Вспоминаем, что он возвращает вместо себя текущее значение x (которое у нас после инкремента равно 6).</li>
59 <li>Подставляем 6 в вычисляемое выражение вместо x--. Получаем: y = 6 + 6.</li>
59 <li>Подставляем 6 в вычисляемое выражение вместо x--. Получаем: y = 6 + 6.</li>
60 <li>Вспоминаем, что не до конца исполнили постдекремент x, осталось уменьшить x на 1. Теперь значение x будет равно 6 - 1. То есть 5.</li>
60 <li>Вспоминаем, что не до конца исполнили постдекремент x, осталось уменьшить x на 1. Теперь значение x будет равно 6 - 1. То есть 5.</li>
61 </ul><p>Вот мы и поработали процессорами (получили вручную те же самые значения):</p>
61 </ul><p>Вот мы и поработали процессорами (получили вручную те же самые значения):</p>
62 <p>х = 5; y = 12.</p>
62 <p>х = 5; y = 12.</p>
63 <p>А теперь пример посложнее (такие дают на экзаменах и собеседованиях).</p>
63 <p>А теперь пример посложнее (такие дают на экзаменах и собеседованиях).</p>
64 int x = 4; int y = ++x * 3 / x-- + --x; System.out.println("x = " + x); System.out.println("y = " + y);<p>Принципиально этот пример не отличается от предыдущего. Только будьте аккуратны при вычислениях. Потому что на этот раз инкременты и декременты меняют значение x трижды в одном выражении.</p>
64 int x = 4; int y = ++x * 3 / x-- + --x; System.out.println("x = " + x); System.out.println("y = " + y);<p>Принципиально этот пример не отличается от предыдущего. Только будьте аккуратны при вычислениях. Потому что на этот раз инкременты и декременты меняют значение x трижды в одном выражении.</p>
65 <p><strong>x = 4.</strong>Вычислим значение выражения ++x * 3 / x-- + --x.</p>
65 <p><strong>x = 4.</strong>Вычислим значение выражения ++x * 3 / x-- + --x.</p>
66 <p>Действуем как и раньше:</p>
66 <p>Действуем как и раньше:</p>
67 <ul><li>Двигаемся слева направо до первого инкремента/декремента. Встречаем ++x (преинкремент x).<p>Как помним, он увеличивает</p>
67 <ul><li>Двигаемся слева направо до первого инкремента/декремента. Встречаем ++x (преинкремент x).<p>Как помним, он увеличивает</p>
68 x на 1 и сразу возвращает вместо себя новое значение x (4 + 1 = 5).<p>Подставляем 5 в наше выражение вместо</p>
68 x на 1 и сразу возвращает вместо себя новое значение x (4 + 1 = 5).<p>Подставляем 5 в наше выражение вместо</p>
69 ++x: 5 * 3 / x-- + --x.</li>
69 ++x: 5 * 3 / x-- + --x.</li>
70 <li>Идём слева направо до первого инкремента/декремента. Встречаем x-- (постдекремент x), заменяем его текущим значением x. Переписываем наше выражение: 5 * 3 / 5 + --x.<p>Вспоминаем, что не до конца исполнили постдекремент</p>
70 <li>Идём слева направо до первого инкремента/декремента. Встречаем x-- (постдекремент x), заменяем его текущим значением x. Переписываем наше выражение: 5 * 3 / 5 + --x.<p>Вспоминаем, что не до конца исполнили постдекремент</p>
71 x, осталось уменьшить x на 1. Теперь значение x станет равно 5 - 1. То есть 4.</li>
71 x, осталось уменьшить x на 1. Теперь значение x станет равно 5 - 1. То есть 4.</li>
72 <li>Вновь двигаемся слева направо до первого инкремента/декремента: 5 * 3 / 5 + --x.<p>Встречаем</p>
72 <li>Вновь двигаемся слева направо до первого инкремента/декремента: 5 * 3 / 5 + --x.<p>Встречаем</p>
73 --x (предекремент x), он уменьшает x на 1 и сразу возвращает вместо себя новое значение x (4 - 1 = 3).<p>Подставляем 3 в наше выражение вместо</p>
73 --x (предекремент x), он уменьшает x на 1 и сразу возвращает вместо себя новое значение x (4 - 1 = 3).<p>Подставляем 3 в наше выражение вместо</p>
74 --x: y = 5 * 3 / 5 + 3.</li>
74 --x: y = 5 * 3 / 5 + 3.</li>
75 <li>Вспоминаем приоритет арифметических операций в Java - и вычисляем значение y.</li>
75 <li>Вспоминаем приоритет арифметических операций в Java - и вычисляем значение y.</li>
76 </ul><p>Узнаём, что y = 6, а x = 3.</p>
76 </ul><p>Узнаём, что y = 6, а x = 3.</p>
77 <p>Запустим код и сверимся с результатом в консоли:</p>
77 <p>Запустим код и сверимся с результатом в консоли:</p>
78 int x = 4; int y = ++x * 3 / x-- + --x; System.out.println("x = " + x); System.out.println("y = " + y); --OUTPUT&gt; x = 3 y = 6<p>Совпало, ура!</p>
78 int x = 4; int y = ++x * 3 / x-- + --x; System.out.println("x = " + x); System.out.println("y = " + y); --OUTPUT&gt; x = 3 y = 6<p>Совпало, ура!</p>
79 <p>Мы познакомились с инкрементом и декрементом, с их префиксной и постфиксной формами в Java, научились вычислять сложные выражения с ними.</p>
79 <p>Мы познакомились с инкрементом и декрементом, с их префиксной и постфиксной формами в Java, научились вычислять сложные выражения с ними.</p>
80 <p>Советуем сразу же потренироваться. Проверить себя можно в любом онлайн-компиляторе Java (даже со смартфона). Удачи на экзамене и собеседовании!</p>
80 <p>Советуем сразу же потренироваться. Проверить себя можно в любом онлайн-компиляторе Java (даже со смартфона). Удачи на экзамене и собеседовании!</p>
81 <a><b>Бесплатный курс по Python ➞</b>Мини-курс для новичков и для опытных кодеров. 4 крутых проекта в портфолио, живое общение со спикером. Кликните и узнайте, чему можно научиться на курсе. Смотреть программу</a>
81 <a><b>Бесплатный курс по Python ➞</b>Мини-курс для новичков и для опытных кодеров. 4 крутых проекта в портфолио, живое общение со спикером. Кликните и узнайте, чему можно научиться на курсе. Смотреть программу</a>