Increment, decrement, and precedence
On This Lesson 11 topics
Lesson Overview
This lesson has two parts that belong together. The first is a pair of tiny operators, ++ and --, that add or subtract one. The second is precedence: the rules that decide which part of a long expression is calculated first. Both are about the same question, "in what order does Java do things?", and getting that order wrong is the source of many wrong answers that look right.
On the calculator from the previous lessons, ++ is a "+1" button. The twist is that you can press it before or after the variable, and the two give different results when used inside a bigger expression. Precedence is the calculator's built-in order of operations: multiplication before addition, as you learned in school, extended to every operator in Java.
Why this matters: counters, ids, and indexes are incremented all the time, and conditions mix arithmetic, comparisons, and logic. If you cannot predict the answer on paper, you cannot find the bug when the program disagrees with you.
This lesson builds on Lessons 1 to 3: arithmetic, comparison and logical operators, and assignment.
Learning Objectives
By the end of this lesson you will be able to:
- Use
++and--as stand-alone statements to add or subtract one. - Explain the difference between prefix (
++i) and postfix (i++) when the result is used. - Predict the values of variables after expressions that mix
++or--with other operators. - Use the precedence order of the operators from this module to evaluate mixed expressions by hand.
- Explain left-to-right grouping for operators of equal precedence, and its effect on
7 / 2 * 2.0. - Use parentheses to make the intended order obvious.
Written Explanation
The increment and decrement operators
i++ adds 1 to i, and i-- subtracts 1. They are shorthand for i += 1 and i -= 1. As their own statement, i++; and ++i; do exactly the same thing:
int n = 3;
n++;
++n;
// n is now 5The operand must be a variable. 5++ is not valid, because there is no box to store the new value in.
Prefix and postfix
Both forms change the variable by one. They differ in the value of the expression itself, which you only see when you use that value:
| Form | Name | What the expression gives | Variable afterwards |
|---|---|---|---|
i++ | postfix | the old value, before the change | old value + 1 |
++i | prefix | the new value, after the change | old value + 1 |
i-- | postfix | the old value | old value - 1 |
--i | prefix | the new value | old value - 1 |
The Java Language Specification says the same thing for each form: postfix returns the value from before the update, and prefix returns the value after it. One way to remember: the symbol's position tells you when the change happens relative to the use. In i++ the variable is used, then it increments. In ++i it increments, then it is used.
int i = 5;
int a = i++; // a gets 5, then i becomes 6
int b = ++i; // i becomes 7, then b gets 7Why you should limit them
An increment that is used inside a larger expression is allowed, but it is hard to read. Consider:
int k = 1;
int r = k++ * 10 + k;Java evaluates operands from left to right (JLS section 15.7). First k++ gives 1 and k becomes 2. Then 1 * 10 is 10, and the second k is read as 2, so r is 12. The answer depends on the order of reading, which is exactly what readers misjudge.
A worse trap: m = m++; leaves m unchanged. The right side gives the old value, the increment happens, and then the assignment stores the old value back over it. Good style: use ++ and -- as separate statements, and use the value of the expression only in simple cases such as int id = next++;.
Precedence: which operator goes first
Precedence is the rule for which operator is applied first when an expression has several. It is the same idea as "multiplication before addition". The Java Tutorials list the operators from highest to lowest precedence. Here is the part you need for this module:
| Level (highest first) | Operators |
|---|---|
| postfix | i++ i-- |
| unary | ++i --i +x -x ! |
| multiplicative | * / % |
| additive | + - |
| relational | < > <= >= |
| equality | == != |
| logical AND | && |
| logical OR | || |
| assignment | = += -= *= /= %= |
Operators on the same row have equal precedence. Operators on a higher row bind more tightly. That is why:
2 + 3 * 4is14, because*is applied before+.10 - 2 * 3 > 3 + 0first does the arithmetic (4 > 3), then the comparison, givingtrue.5 > 3 && 2 + 2 == 4 || falsedoes the arithmetic, then the comparisons, then&&, then||.- Assignment is last, so
x = 2 + 3computes the sum before storing.
This table is why Lessons 1 to 3 worked: n % 2 == 0 applies % first, then ==, and cartItems > 0 && !suspended applies the comparison and the ! before the &&.
Equal precedence: left to right
When two operators from the same row appear next to each other, Java groups them from the left (assignment is the exception: it groups from the right, as you saw with a = b = 7).
20 - 5 - 3is(20 - 5) - 3, which is12. It is not20 - (5 - 3), which is18.7 / 2 * 2.0is(7 / 2) * 2.0. The7 / 2is integer division and gives3, so the result is6.0. Compare7 / (2 * 2.0), which is1.75.2 + 3 * 4 % 5:*and%are on the same row, so3 * 4is12, then12 % 5is2, then2 + 2is4.
The second example is a trap worth remembering: the type of each division is decided by its own two operands, so an early int / int can drop the fraction even if a double appears later in the expression.
Parentheses
Parentheses override precedence. They are evaluated first, innermost first. You do not have to memorize the whole table. A good rule is: know the big ordering (arithmetic, then comparison, then &&, then ||), and add parentheses whenever a reader could hesitate. (a && b) || c has the same meaning as a && b || c, and it is much safer to read.
Examples
Example 1: prefix versus postfix (simple)
public class Inc {
public static void main(String[] args) {
int i = 5;
int a = i++;
System.out.println("a=" + a + " i=" + i);
int b = ++i;
System.out.println("b=" + b + " i=" + i);
int c = i--;
System.out.println("c=" + c + " i=" + i);
int d = --i;
System.out.println("d=" + d + " i=" + i);
int k = 1;
int r = k++ * 10 + k;
System.out.println("r=" + r + " k=" + k);
int m = 3;
m = m++;
System.out.println("m=" + m);
int n = 3;
n++;
++n;
System.out.println("n=" + n);
}
}Output (JDK 21):
a=5 i=6
b=7 i=7
c=7 i=6
d=5 i=5
r=12 k=2
m=3
n=5Line 1: postfix gave the old 5. Line 2: prefix gave the new 7. Lines 3 and 4 repeat the pattern with --. Line 5 is the k++ * 10 + k example from above, line 6 is the unchanged m, and line 7 shows that stand-alone n++ and ++n act the same.
Example 2: precedence on paper, then in code (practical)
public class Prec {
public static void main(String[] args) {
System.out.println(2 + 3 * 4);
System.out.println((2 + 3) * 4);
System.out.println(20 - 5 - 3);
System.out.println(20 - (5 - 3));
System.out.println(7 / 2 * 2.0);
System.out.println(7 / (2 * 2.0));
System.out.println(2 + 3 * 4 % 5);
System.out.println(10 - 2 * 3 > 3 + 0);
int x = 4;
System.out.println(-x * 2);
System.out.println(1 + 2 < 4 == true);
System.out.println(5 > 3 && 2 + 2 == 4 || false);
}
}14
20
12
18
6.0
1.75
4
true
-8
true
trueEach pair of neighbours (lines 1 and 2, 3 and 4, 5 and 6) differs only by parentheses. Line 10 reads ((1 + 2) < 4) == true: the arithmetic first, then < (relational, higher), then ==.
Example 3: ids, stock, and a discount (realistic)
public class Ticket {
public static void main(String[] args) {
int nextId = 100;
int first = nextId++;
int second = nextId++;
int third = ++nextId;
System.out.println(first + " " + second + " " + third + " next=" + nextId);
int stock = 3;
stock--;
stock--;
System.out.println("stock=" + stock);
int price = 1000;
int qty = 3;
int discountPercent = 10;
int total = price * qty - price * qty * discountPercent / 100;
System.out.println(total);
boolean ok = total > 2000 && qty >= 3 || stock == 0;
System.out.println(ok);
}
}100 101 103 next=103
stock=1
2700
trueThe first line: first takes 100, second takes 101, and third takes 103, because the prefix form increments to 103 before it is used, skipping 102. This is a classic id-skipping bug, and it comes from choosing prefix when postfix was meant. total is 3000 - 300, since the multiplications and division happen before the subtraction.
Backend Insight
Counters and ids appear everywhere in backend code: request counts, retry attempts, array positions, sequence numbers. count++ as a stand-alone line is by far the most common form, and that is the form to prefer. When an id is generated, the choice between "use the old value, then advance" and "advance, then use" decides whether ids start at 100 or 101, or skip a number. In real systems ids usually come from the database, which is safer than a counter in memory, but the thinking is the same.
Precedence matters in the conditions that guard business rules, such as isAdmin || isOwner && !locked. The meaning of that line, and who can access what, depends entirely on the grouping. In reviews and in security-sensitive code, parentheses are cheap insurance. Later chapters on debugging and test boundaries rely on your ability to evaluate an expression step by step, exactly as this lesson trains.
Common Mistakes
Mistake 1: Confusing prefix and postfix
- Incorrect: expecting
int b = i++;to give the new value. - Correct: postfix
i++gives the old value; use++iwhen you want the new one.
Mistake 2: i = i++
The variable ends up with its old value. Write i++; on its own line instead.
Mistake 3: Early integer division
7 / 2 * 2.0 is 6.0, not 7.0. The first division uses two ints. If you want decimals, start with one: 7 / 2.0 * 2.
Mistake 4: Grouping subtraction wrongly
20 - 5 - 3 is 12, because equal-precedence operators group from the left.
Mistake 5: Relying on precedence you cannot recite
If you need to look up the order, so will the next reader. Add parentheses.
Mistake 6: Using several increments of one variable in one expression
An expression such as i++ + ++i is legal but nobody should have to decode it. Split it into separate statements.
Exercises
Try each exercise yourself before opening the solutions. Write your prediction first.
Level A: Foundation
A1. Evaluate: 3 + 4 * 2, (3 + 4) * 2, 12 / 3 / 2, 12 / (3 / 2).
Show solution A1
A1. 11, 14, 2 ((12 / 3) / 2), and 12 (3 / 2 is 1 in integer division, so 12 / 1).
A2. After int i = 10; i++; i--; i--;, what is i?
Show solution A2
A2. 9. Starting at 10, i++ makes 11, the first i-- makes 10, and the second i-- makes 9.
A3. After int i = 4; int j = i--;, what are i and j?
Show solution A3
A3. j gets the old value 4, then i becomes 3. So i is 3 and j is 4.
Level B: Application
B1. Predict p and q: int p = 5; int q = ++p * 2;
Show solution B1
B1. ++p makes p 6 and gives 6, then 6 * 2 is 12. So p is 6 and q is 12.
B2. Evaluate by hand, showing the order of steps: 1 + 2 * 3 - 4 / 2 + 5 % 3.
Show solution B2
B2. 2 * 3 is 6; 4 / 2 is 2; 5 % 3 is 2. The expression becomes 1 + 6 - 2 + 2, which is evaluated from the left: 7, then 5, then 7. The answer is 7.
B3. Evaluate: 2 + 3 > 4 && 10 % 3 == 1 || false. Which operator is applied last?
Show solution B3
B3. 2 + 3 > 4 is 5 > 4, which is true. 10 % 3 == 1 is 1 == 1, which is true. Then true && true is true, and true || false is true. The || is applied last; the answer is true.
Level C: Challenge
C1. int a = 3; int b = a++ * 2 + a; then int c = ++a * 2 + a; Give a, b, and c at the end.
Show solution C1
C1. b = a++ * 2 + a: a++ gives 3 and a becomes 4, 3 * 2 is 6, plus the current a (4) gives b = 10. Then ++a makes a 5 and gives 5, 5 * 2 is 10, plus a (5) gives c = 15. Final values: a = 5, b = 10, c = 15.
C2. A formula for the average of three ints x, y, z is written x + y + z / 3.0. Explain what it really computes, using x = 3, y = 6, z = 9, and fix it.
Show solution C2
C2. Division binds tighter than addition, so it computes x + y + (z / 3.0), which is 3 + 6 + 3.0 = 12.0, not the average (6.0). Fix: (x + y + z) / 3.0, which gives 6.0.
Mini Challenge
Write a program Steps with an int level = 1; and print a line after each step:
- A stand-alone
level++;. int shown = level++;and print bothshownandlevel.int next = ++level * 2;and printnextandlevel.- Print the value of
1 + level * 2 > 10 && level % 2 == 1(predict with the table first).
Check your work: write your predictions on paper before you run the program. After step 1 the level is 2; after step 2 shown is 2 and level is 3; after step 3 next is 8 and level is 4, and the last expression is false.
Summary & Next Lesson
Key takeaways
++and--add or subtract one. As a stand-alone statement the prefix and postfix forms are identical.- In an expression, postfix (
i++) gives the old value and prefix (++i) gives the new one. Both change the variable by one. - Precedence, high to low: postfix and unary, then
* / %, then+ -, then comparisons, then&&, then||, then assignment. - Equal precedence groups from the left, so
20 - 5 - 3is12and7 / 2 * 2.0is6.0. - Parentheses make the order explicit; use them whenever a reader could hesitate.
Next lesson
Next is "Short-circuit evaluation": how && and || sometimes skip their right side entirely, and how to use that to write conditions that can never crash.
Self-check
- After
int i = 1; int j = i++;, what areiandj? - After
int i = 1; int j = ++i;, what areiandj? - What is
8 - 3 * 2? - What is
100 / 10 / 5? - What do you do when you are not sure how an expression will be grouped?
Show answers
iis2andjis1.iis2andjis2.2: the multiplication gives 6 first, and8 - 6is2.2. It is(100 / 10) / 5, which is10 / 5.- Add parentheses so the order is explicit, and check the result with a small test.
References
- Oracle, The Java Tutorials: Operators. It provides the operator precedence table used above and the rule that binary operators other than assignment are evaluated left to right.
- Oracle, The Java Language Specification, Java SE 21, Chapter 15: Expressions. Sections 15.14.2 and 15.15.1 say that postfix increment gives the value before the update and prefix increment gives the value after it. Section 15.7 says operands are evaluated left to right.
- All outputs above came from compiling and running the code with JDK 21.
Practice
Apply this lesson with the module's lab, exercises and quiz.
Marking a lesson complete is optional and you can undo it any time. Your progress stays in this browser.