Master all Java operator categories, write clear conditional logic with if-else and switch expressions, and control iteration with for, while, do-while, and enhanced for-each loops.
Every useful program makes decisions and repeats operations. Whether validating a form, processing a list of orders, or implementing a game loop, control flow constructs determine which code runs and how many times. Java's control flow is similar to C and C# but adds important modern features: the switch expression (Java 14) eliminates fall-through bugs, records and pattern matching (Java 16+) simplify branching on types, and sealed classes give exhaustive switch analysis.
Operator precedence determines the order Java evaluates complex expressions. Getting it wrong is a common source of subtle bugs — a + b * c multiplies first because * has higher precedence than +. In this lesson you will gain complete command of Java's operators and control flow constructs, understand where parentheses are needed for clarity, and learn the switch expression patterns used in modern Java codebases.
1// Arithmetic operators
2int a = 10, b = 3;
3System.out.println(a + b); // 13 addition
4System.out.println(a - b); // 7 subtraction
5System.out.println(a * b); // 30 multiplication
6System.out.println(a / b); // 3 integer division (truncates)
7System.out.println(a % b); // 1 modulo (remainder)
8System.out.println(10.0 / 3); // 3.3333... floating-point division
9
10// Compound assignment
11int x = 10;
12x += 5; // x = x + 5 = 15
13x -= 3; // x = x - 3 = 12
14x *= 2; // x = x * 2 = 24
15x /= 4; // x = x / 4 = 6
16x %= 4; // x = x % 4 = 2
17
18// Increment and decrement
19int n = 5;
20System.out.println(n++); // 5 — post-increment: returns THEN increments
21System.out.println(n); // 6
22System.out.println(++n); // 7 — pre-increment: increments THEN returns
23System.out.println(n--); // 7 — post-decrement
24System.out.println(n); // 6
25
26// Common modulo pattern: checking even/odd
27for (int i = 1; i <= 10; i++) {
28 String type = (i % 2 == 0) ? "even" : "odd";
29 System.out.printf("%d is %s%n", i, type);
30}
31
32// Integer division pitfall
33int percent = 1 / 3; // 0 — integer division!
34double correct = 1.0 / 3; // 0.333...
35double also = (double) 1 / 3; // 0.333... — cast one operand1// Relational operators (return boolean)
2int x = 10;
3boolean gt = x > 5; // true
4boolean lt = x < 5; // false
5boolean ge = x >= 10; // true
6boolean le = x <= 10; // true
7boolean eq = x == 10; // true
8boolean ne = x != 10; // false
9
10// Logical operators
11boolean a = true, b = false;
12System.out.println(a && b); // false — AND: both must be true
13System.out.println(a || b); // true — OR: at least one true
14System.out.println(!a); // false — NOT: negates
15
16// Short-circuit evaluation — CRITICAL for null safety
17String s = null;
18// Without short-circuit: s.length() would throw NullPointerException
19if (s != null && s.length() > 0) { // safe: s.length() never called if s==null
20 System.out.println("Non-empty: " + s);
21}
22
23// & and | are non-short-circuit (evaluate both sides)
24boolean result = isExpensive() & isAlsoExpensive(); // both called always
25
26// Bitwise operators (on integer types)
27int p = 0b1010; // 10 in binary
28int q = 0b1100; // 12 in binary
29System.out.println(Integer.toBinaryString(p & q)); // 1000 (8) AND
30System.out.println(Integer.toBinaryString(p | q)); // 1110 (14) OR
31System.out.println(Integer.toBinaryString(p ^ q)); // 0110 (6) XOR
32System.out.println(Integer.toBinaryString(~p)); // ...110101 NOT
33
34// Shift operators
35int flags = 1;
36int shifted = flags << 3; // 8 — left shift (multiply by 2^3)
37int halved = 16 >> 2; // 4 — signed right shift (divide by 2^2)
38int logical = -1 >>> 1; // fills with 0 (unsigned right shift)
39
40// Ternary operator: condition ? valueIfTrue : valueIfFalse
41int age = 20;
42String status = (age >= 18) ? "adult" : "minor";
43String grade = score >= 90 ? "A" : score >= 80 ? "B" : score >= 70 ? "C" : "F";1// if-else-if chain
2int score = 85;
3if (score >= 90) {
4 System.out.println("A");
5} else if (score >= 80) {
6 System.out.println("B"); // prints this
7} else if (score >= 70) {
8 System.out.println("C");
9} else {
10 System.out.println("F");
11}
12
13// Traditional switch statement (fall-through — error prone)
14switch (score / 10) {
15 case 10:
16 case 9: System.out.println("A"); break; // need break!
17 case 8: System.out.println("B"); break;
18 default: System.out.println("Below B"); break;
19}
20
21// Java 14+ switch EXPRESSION (preferred — no fall-through, returns value)
22String grade = switch (score / 10) {
23 case 10, 9 -> "A"; // arrow syntax: no fall-through, no break needed
24 case 8 -> "B";
25 case 7 -> "C";
26 case 6 -> "D";
27 default -> "F";
28};
29System.out.println(grade);
30
31// Switch expression with blocks and yield
32String description = switch (score / 10) {
33 case 10, 9 -> "Excellent";
34 case 8 -> {
35 String msg = "Good job, score: " + score;
36 yield msg; // yield returns the value from a block
37 }
38 default -> "Keep practicing";
39};
40
41// Pattern matching in switch (Java 21)
42Object obj = "Hello";
43String result = switch (obj) {
44 case Integer i -> "Integer: " + i;
45 case String s -> "String of length " + s.length();
46 case null -> "null value";
47 default -> "Unknown: " + obj.getClass().getSimpleName();
48};
49System.out.println(result); // "String of length 5"1// Classic for loop: index-based iteration
2for (int i = 0; i < 5; i++) {
3 System.out.print(i + " "); // 0 1 2 3 4
4}
5
6// Counting down
7for (int i = 10; i >= 0; i -= 2) {
8 System.out.print(i + " "); // 10 8 6 4 2 0
9}
10
11// Multiple variables in for loop
12for (int i = 0, j = 10; i < j; i++, j--) {
13 System.out.printf("i=%d j=%d%n", i, j);
14}
15
16// while loop: executes WHILE condition is true
17int count = 0;
18while (count < 5) {
19 System.out.print(count + " ");
20 count++;
21}
22
23// Reading until sentinel (common I/O pattern)
24Scanner scanner = new Scanner(System.in);
25String input;
26while (!(input = scanner.nextLine()).equals("quit")) {
27 System.out.println("You typed: " + input);
28}
29
30// do-while: executes AT LEAST ONCE
31int menu;
32do {
33 System.out.println("1) New 2) Open 3) Quit");
34 menu = scanner.nextInt();
35} while (menu != 3);
36
37// Enhanced for-each: iterates over arrays and Iterable collections
38int[] numbers = {5, 3, 8, 1, 9, 2};
39for (int n : numbers) {
40 System.out.print(n + " ");
41}
42
43List<String> names = List.of("Alice", "Bob", "Charlie");
44for (String name : names) {
45 System.out.println("Hello, " + name);
46}
47
48// break and continue
49for (int i = 0; i < 10; i++) {
50 if (i == 3) continue; // skip 3
51 if (i == 7) break; // stop at 7
52 System.out.print(i + " "); // 0 1 2 4 5 6
53}
54
55// Labeled break for nested loops
56outerLoop:
57for (int row = 0; row < 3; row++) {
58 for (int col = 0; col < 3; col++) {
59 if (row == 1 && col == 1) break outerLoop; // exits both loops
60 System.out.printf("[%d,%d] ", row, col);
61 }
62}Operator precedence determines evaluation order when multiple operators appear in one expression. Misunderstanding precedence is a source of subtle bugs.
1// Precedence (high to low, simplified):
2// 1. () [] . — parentheses, array access, member access
3// 2. ++ -- ! ~ — unary
4// 3. * / % — multiplicative
5// 4. + - — additive
6// 5. << >> >>> — shift
7// 6. < > <= >= — relational
8// 7. == != — equality
9// 8. & — bitwise AND
10// 9. ^ — bitwise XOR
11// 10. | — bitwise OR
12// 11. && — logical AND
13// 12. || — logical OR
14// 13. ?: — ternary
15// 14. = += -= ... — assignment
16
17// Examples
18int result1 = 2 + 3 * 4; // 14 (not 20): * before +
19int result2 = (2 + 3) * 4; // 20: parentheses override
20boolean b1 = true || false && false; // true: && before ||
21boolean b2 = (true || false) && false; // false: parentheses change order
22
23// Common pitfalls
24// Pitfall 1: == vs = in conditions
25int x = 5;
26// if (x = 10) { } // COMPILE ERROR: assignment in condition
27if (x == 10) { } // correct: equality check
28
29// Pitfall 2: integer division
30int total = 7, count = 2;
31double avg1 = total / count; // 3.0 — integer division first!
32double avg2 = (double) total / count; // 3.5 — correct
33
34// Pitfall 3: post vs pre increment in expressions
35int n = 5;
36int y = n++ + n++; // 5 + 6 = 11 (n becomes 7)
37System.out.println(y); // 11
38System.out.println(n); // 7
39
40// Best practice: avoid multiple side effects in one expression
41// Keep it simple and readable
42int a = n++;
43int b2 = n++;
44int total2 = a + b2; // much clearerA complete program that uses if-else, switch expressions, all loop types, and break/continue to implement a grade calculator with statistics.
1import java.util.ArrayList;
2import java.util.List;
3
4/**
5 * GradeCalculator.java
6 * Demonstrates all control flow constructs in a realistic grade processing scenario.
7 */
8public class GradeCalculator {
9
10 // Grade boundaries as constants
11 static final int A_MIN = 90;
12 static final int B_MIN = 80;
13 static final int C_MIN = 70;
14 static final int D_MIN = 60;
15
16 public static void main(String[] args) {
17 int[] scores = {95, 82, 67, 55, 91, 74, 88, 42, 79, 63};
18
19 System.out.println("=== Grade Calculator ===");
20 printGrades(scores);
21 printStatistics(scores);
22 printDistribution(scores);
23 printTopScores(scores, 80);
24 }
25
26 static void printGrades(int[] scores) {
27 System.out.println("\n--- Individual Grades ---");
28 for (int i = 0; i < scores.length; i++) {
29 int score = scores[i];
30 // Switch expression: concise, no fall-through
31 String grade = switch (score / 10) {
32 case 10, 9 -> "A";
33 case 8 -> "B";
34 case 7 -> "C";
35 case 6 -> "D";
36 default -> "F";
37 };
38 String status = (score >= 60) ? "PASS" : "FAIL";
39 System.out.printf("Student %2d: %3d → %s (%s)%n",
40 i + 1, score, grade, status);
41 }
42 }
43
44 static void printStatistics(int[] scores) {
45 System.out.println("\n--- Statistics ---");
46 int sum = 0, min = scores[0], max = scores[0];
47 int passCount = 0, failCount = 0;
48
49 for (int score : scores) { // enhanced for-each
50 sum += score;
51 if (score < min) min = score;
52 if (score > max) max = score;
53 if (score >= 60) passCount++;
54 else failCount++;
55 }
56
57 double avg = (double) sum / scores.length;
58 System.out.printf("Count : %d%n", scores.length);
59 System.out.printf("Average : %.2f%n", avg);
60 System.out.printf("Minimum : %d%n", min);
61 System.out.printf("Maximum : %d%n", max);
62 System.out.printf("Passing : %d/%d%n", passCount, scores.length);
63 System.out.printf("Failing : %d/%d%n", failCount, scores.length);
64 }
65
66 static void printDistribution(int[] scores) {
67 System.out.println("\n--- Grade Distribution ---");
68 int[] buckets = new int[5]; // A, B, C, D, F
69
70 for (int score : scores) {
71 int bucket;
72 if (score >= A_MIN) bucket = 0;
73 else if (score >= B_MIN) bucket = 1;
74 else if (score >= C_MIN) bucket = 2;
75 else if (score >= D_MIN) bucket = 3;
76 else bucket = 4;
77 buckets[bucket]++;
78 }
79
80 String[] labels = {"A", "B", "C", "D", "F"};
81 for (int i = 0; i < labels.length; i++) {
82 // Build bar using while loop
83 StringBuilder bar = new StringBuilder();
84 int count = buckets[i];
85 while (count-- > 0) { // post-decrement in condition
86 bar.append("*");
87 }
88 System.out.printf("%s: %-10s (%d)%n", labels[i], bar, buckets[i]);
89 }
90 }
91
92 static void printTopScores(int[] scores, int threshold) {
93 System.out.printf("%n--- Scores above %d ----%n", threshold);
94 boolean found = false;
95 int rank = 1;
96
97 // do-while with break demonstrates both constructs
98 int i = 0;
99 do {
100 int score = scores[i];
101 if (score < threshold) {
102 i++;
103 continue; // skip scores below threshold
104 }
105 System.out.printf("Rank %d: %d%n", rank++, score);
106 found = true;
107 i++;
108 } while (i < scores.length);
109
110 if (!found) {
111 System.out.printf("No scores above %d found.%n", threshold);
112 }
113
114 // Demonstrate labeled break in nested search
115 System.out.println("\n--- Searching for consecutive scores > 80 ---");
116 outerLoop:
117 for (int row = 0; row < scores.length - 1; row++) {
118 for (int j = row + 1; j < scores.length; j++) {
119 if (scores[row] > 80 && scores[j] > 80) {
120 System.out.printf("Found consecutive: scores[%d]=%d, scores[%d]=%d%n",
121 row, scores[row], j, scores[j]);
122 break outerLoop; // exits both loops
123 }
124 }
125 }
126 }
127}This program applies every major control flow construct to a realistic grade processing scenario: the switch expression calculates letter grades without fall-through, the enhanced for-each iterates over score arrays cleanly, a do-while loop demonstrates at-least-once iteration with continue, a while loop builds histogram bars with post-decrement in the condition, and labeled break exits nested loops cleanly. The constants A_MIN through D_MIN centralize the boundary values, making the thresholds easy to change in one place.
With control flow mastered, the next lesson covers arrays and strings — Java's fundamental data structures for storing sequences of values and text. You will learn single and multi-dimensional arrays, the String class's immutability, StringBuilder for efficient string building, and the most commonly used String methods in real applications.
Your progress is saved in this browser, on this device only.