Demo: predict-then-run expression challenge
On This Lesson 11 topics
Lesson Overview
This is a guided demo, and its goal is a habit rather than a new operator. You will take a set of expressions that use everything from this module (integer division, remainder, precedence, prefix and postfix, short-circuiting), predict each result on paper first, then run them and compare. Where the program disagrees with you, you will find out why.
Why predict first? When you only run code, a wrong result teaches nothing unless you already know what you expected. Predicting is like a calculator check: estimate the answer before you press the buttons. An answer that is far from the estimate tells you something is wrong, even when no error message appears. In this module almost every mistake produces a plausible number, not an error, so the prediction is the only alarm you have.
The demo prepares the module's lab, BEG-010-LAB1, "Expression predictor", which uses the same method with 20 different expressions.
This lesson builds on Lessons 1 to 5. Use a terminal (javac and java) or an IDE such as IntelliJ IDEA; menus differ between versions and operating systems, so look for the equivalent action. The outputs below come from JDK 21.
Learning Objectives
By the end of this lesson you will be able to:
- Predict the value of expressions that combine arithmetic, comparison, logical, and increment operators.
- Record a prediction, a result, and a one-line reason for each mismatch.
- Explain why
1 + 2 + "3"is"33"and"x=" + 1 + 2is"x=12". - Use a step-by-step method (parentheses, then precedence, then left to right) to evaluate an expression by hand.
- Diagnose a wrong prediction by finding which rule you misapplied.
Written Explanation
The method
Use the same five steps for every expression:
- Write the types. Mark each operand as
int,double,String, orboolean. Many wrong predictions come from forgetting a type. - Add parentheses where Java would group things: first
++/--, then* / %, then+ -, then comparisons, then&&, then||(Lesson 4). - Evaluate step by step, innermost parentheses first, equal-precedence operators left to right.
- Write the prediction with its type, such as
3versus3.0. Do this before running anything. - Run, compare, explain. For each mismatch, write one line: which rule did you misapply?
The prediction table you will fill in looks like this:
| # | Expression | Prediction | Result | Why (if different) |
|---|
One more rule: + with text
You have used + between text and numbers since BEG-009. Here is the precise rule, which this demo needs. The Java Language Specification says that if either operand of + is a String, the operation is string concatenation, and the other operand is converted to text. It also says + groups left to right. Together:
1 + 2 + "3": first1 + 2(two ints) is3; then3 + "3"has aString, so it joins as text:"33"."x=" + 1 + 2: first"x=" + 1is"x=1"; then"x=1" + 2is"x=12". No addition of 1 and 2 ever happens."x=" + (1 + 2): parentheses first, so"x=3".
The number is not added until the text stops being involved. One extra detail: 'a' + 1 has no String, so it is numeric addition and gives the int 98 (the character a is stored as a number, as BEG-009 mentioned for char arithmetic). By contrast, "" + 'a' + 1 starts with a String and gives "a1".
Examples
Example 1: the first four predictions (simple)
Create Predict.java with the first four expressions below. Before you run, copy the table above and write your prediction for each into the Prediction column.
public class Predict {
public static void main(String[] args) {
System.out.println("1: " + 17 / 5);
System.out.println("2: " + 17 % 5);
System.out.println("3: " + 17 / 5.0);
System.out.println("4: " + (2 + 3 * 4 % 5));
// more lines come in the next examples
}
}Here is the reasoning you should have done:
17 / 5: two ints, so integer division:3. (Not 3.4.)17 % 5:3 * 5 = 15, remainder2.17 / 5.0: adoubleoperand, so decimals:3.4.2 + 3 * 4 % 5:*and%have equal precedence and group from the left.3 * 4is12,12 % 5is2,2 + 2is4.
(The "1: " + ... part is just a label. Lines 1 to 3 do not need parentheses because the division happens before the +; line 4 needs them so that the + inside is arithmetic and not text.)
Example 2: increments, text, and short-circuiting (practical)
Now add the next expressions in the same method and predict each one before running.
int i = 4;
int a = i++ + i;
System.out.println("5: a=" + a + " i=" + i);
System.out.println("6: " + (1 + 2 + "3"));
System.out.println("7: " + ("x=" + 1 + 2));
int d = 0;
System.out.println("8: " + (d != 0 && 10 / d > 1));
System.out.println("9: " + (false && true || true));
System.out.println("10: " + (10 / 4 * 4.0));Reasoning for each:
i++ + i: operands are read left to right.i++gives4andibecomes5; then the secondiis5. Soais9andiis5.1 + 2 + "3": this is the one expected to catch you. Many people predict6. Following the rule above, it is"33"."x=" + 1 + 2:"x=12".- The guard from Lesson 5:
d != 0isfalse, so the division is skipped. The result isfalse, with no crash. &&groups before||:(false && true) || trueisfalse || true, which istrue.10 / 4 * 4.0: left to right,10 / 4is integer division (2), then2 * 4.0is8.0. Thedoubleappears too late to save the fraction.
Run the program with javac Predict.java followed by java Predict. The output, in JDK 21, is:
1: 3
2: 2
3: 3.4
4: 4
5: a=9 i=5
6: 33
7: x=12
8: false
9: true
10: 8.0If your table has a mismatch, do not just correct the prediction. Write the reason, as in the next example.
Example 3: the mistake log (realistic)
Imagine a developer who predicted line 6 as 6 and line 10 as 10.0. Their completed table might look like this:
| # | Expression | Prediction | Result | Why (if different) |
|---|---|---|---|---|
| 6 | 1 + 2 + "3" | 6 | 33 | 1 + 2 is 3 first, then a String is involved, so + joins text |
| 10 | 10 / 4 * 4.0 | 10.0 | 8.0 | 10 / 4 is integer division (2), done before the double is used |
Each "Why" is one sentence naming a rule, not "I was wrong". The sentences matter more than the numbers: they are a list of the rules you tend to forget. A second program shows more text and char cases:
public class Predict2 {
public static void main(String[] args) {
int x = 9;
x -= 2 * 3;
System.out.println(x);
System.out.println("n=" + 1 + 2);
System.out.println("n=" + (1 + 2));
System.out.println(1 + 2 + "n");
System.out.println('a' + 1);
System.out.println("" + 'a' + 1);
}
}3
n=12
n=3
3n
98
a1First line: x -= 2 * 3 is x = x - (2 * 3), so 9 - 6 is 3. The "n=" + (1 + 2) line shows parentheses repairing the text mix-up that "n=" + 1 + 2 causes. This is a real bug source: a message such as "Total: " + price + tax prints two numbers side by side instead of adding them.
Backend Insight
Backend developers do this kind of predicting all day, usually without the table. A wrong total in an invoice, a skipped record in a report, or an access check that passes when it should not: each is an expression that gave a plausible but wrong answer. The prediction habit is what turns a vague "it gives the wrong number" into "I expected 8.0, got 10.0, so the division happens as integers", which is a bug you can fix.
The habit also shapes testing. A test is a recorded prediction: "for these inputs, this expression should give this output". The tests you will write in the testing modules are exactly this table, saved in code, and the values worth testing are the boundaries you met here: zero divisors, > versus >=, the first and last number of a range. Log messages that glue values with + are another place where the text rule from this lesson bites.
Common Mistakes
Mistake 1: Running before predicting
If you run first, you will rationalize whatever you see ("yes, that is what I thought"). Write the prediction down before running, in a file or on paper.
Mistake 2: Predicting 1 + 2 + "3" as 6
Once one side of + is text, the operation joins. Evaluate left to right, one operator at a time.
Mistake 3: Forgetting the type of each step
10 / 4 * 4.0 is 8.0, not 10.0, because the type of the first division is int. Predict the type as well as the value (3 is not 3.0).
Mistake 4: Fixing the prediction instead of explaining it
A silently corrected prediction teaches nothing. Always write the rule you got wrong in one line.
Mistake 5: Assuming "no error" means "correct"
All ten expressions above run without an error message; one of them is wrong in most people's heads. Compare the output with your prediction, not with "did it crash".
Exercises
Do each exercise on paper before running anything, and fill in a prediction table with a reason for every mismatch.
Level A: Foundation
A1. Predict, with the type of each result: 9 / 2, 9 % 2, 9 / 2.0, 9 > 2.
Show solution A1
A1. 4 (int), 1 (int), 4.5 (double), true (boolean).
A2. Predict: "a" + 1 + 1, 1 + 1 + "a", "a" + (1 + 1).
Show solution A2
A2. "a11", "2a", "a2".
A3. int n = 5; n *= 3 + 1; What is n?
Show solution A3
A3. 20. The right side 3 + 1 is 4, and 5 * 4 is 20.
Level B: Application
B1. Predict p, q, and the printed value: int p = 2; int q = p++ * 3 + p; System.out.println(q > p && q % 2 == 1);
Show solution B1
B1. p++ gives 2 and p becomes 3; 2 * 3 is 6; the second p is 3, so q is 9. Then q > p is 9 > 3, which is true, and q % 2 == 1 is 1 == 1, which is true. It prints true; p is 3 and q is 9.
B2. Predict the output (and say whether any line could crash):
int d = 3;
System.out.println(d > 0 && 12 / d > 3);
d = 0;
System.out.println(d > 0 && 12 / d > 3);
System.out.println(d == 0 || 12 / d > 3);Show solution B2
B2. true (12 / 3 is 4, and 4 > 3), then false (the guard d > 0 fails and the division is skipped), then true (d == 0 is true, so the division is skipped). No line crashes.
B3. Predict 8 - 4 / 3 * 3 + 1 % 2 and show each step.
Show solution B3
B3. 4 / 3 is 1; 1 * 3 is 3; 1 % 2 is 1. The expression becomes 8 - 3 + 1, evaluated from the left: 8 - 3 is 5, then 5 + 1 is 6. The answer is 6.
Level C: Challenge
C1. Without running anything, write six expressions of your own that each test a different rule from the module (one for integer division, one for %, one for prefix versus postfix, one for precedence, one for short-circuiting, one for the text rule). Give your prediction for each. Then run them and log any mismatch.
Show solution C1
C1. There is no single right answer. A good set: 13 / 4 (3), 13 % 4 (1), int k = 2; k++ + k (5, with k equal to 3), 1 + 2 * 3 (7), n != 0 && 6 / n > 1 with n = 0 (false, no crash), and "v" + 1 + 1 ("v11"). Check that each of yours tests a different rule and that your log has a reason for every mismatch.
C2. A teammate wrote System.out.println("Sum: " + a + b); with a = 3 and b = 4 and is surprised by the output. Predict the output, explain it, and give two different fixes.
Show solution C2
C2. The output is Sum: 34. The expression groups as ("Sum: " + a) + b, so b is appended as text. Fixes: add parentheses, "Sum: " + (a + b), which prints Sum: 7; or compute first: int sum = a + b; and print "Sum: " + sum.
Mini Challenge
Prepare for the lab. Write five new expressions of your own (not copied from this lesson) that are likely to trip you up, for example one that mixes int and double division, one with % and a negative number, one with ++ inside an expression, one that mixes && and ||, and one with + and a String.
- Predict all five on paper with their types.
- Put them in a program, run it, and fill a table with the result and a one-line reason for every mismatch.
- Add a short comment at the top of the file summarizing which rule you most often got wrong.
Check your work: every prediction was written before running, and the "Why" column has a rule name (such as "integer division", "postfix", "left to right") in each mismatch row, not just a corrected number.
Summary & Next Lesson
Key takeaways
- Predict first, run second, explain every mismatch with a rule. It is the cheapest debugging skill there is.
- Method: write the types, add parentheses by precedence, evaluate left to right, and record the type of the result.
- Once a
Stringis involved,+joins text.1 + 2 + "3"is"33"and"x=" + 1 + 2is"x=12". - Integer division,
%, prefix versus postfix, precedence, and short-circuiting each change a result without any error message. - The mismatch log is a personal list of rules to watch.
Next lesson
This was the last lesson of the module. Next comes the module's lab, BEG-010-LAB1, "Expression predictor": predict 20 expressions on paper, then run them, and explain each mismatch.
Self-check
- Why should you write the prediction before running the code?
- What is
1 + 2 + "3", and why? - What is
10 / 4 * 4.0? - In
int a = i++ + i;withi = 4, what areaandi? - What should the "Why" column contain when a prediction was wrong?
Show answers
- Otherwise you will tend to accept whatever the program prints, and you cannot tell a surprise from an expected result.
"33".1 + 2is3first; then adding aStringmakes+join text.8.0: integer division gives2first, then2 * 4.0.ais9andiis5.- The specific rule that was misapplied, in one sentence, such as "integer division happens first".
References
- Oracle, The Java Language Specification, Java SE 21, Chapter 15: Expressions. Section 15.18 says that if either operand of
+is aStringthe operation is string concatenation, and that additive operators group left to right; section 15.18.1 gives1 + 2 + " fiddlers"as"3 fiddlers"and"fiddlers " + 1 + 2as"fiddlers 12". Section 15.7 gives left-to-right evaluation of operands. - Oracle, The Java Tutorials: Operators. It supports the precedence order used in the method.
- All outputs above came from compiling and running the code with JDK 21. That
'a' + 1is theint98follows from the promotion ofchartointin arithmetic, which BEG-009 introduced, and the printed98was confirmed by running the code. The claim that this method is the "cheapest debugging skill" is the author's opinion, not a sourced fact.
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.