Syntax of Java Programs
Syntax is the form a program must take, and the source stresses that knowing syntax is only part of being a successful programmer.
Predicting Before You Read
Imagine you have written a Java program. You typed it carefully, the compiler accepted it, and it ran without complaint. Does that mean the program is finished? Not necessarily. A program can be written in valid form and still produce a result you did not want. Nothing about the program's shape tells you whether the number it prints is the number you needed.
Before reading any explanation, try to predict what the following short Java program does. It declares integer variables, combines them, divides the result by an integer, and prints it. The question is not whether the code is valid. The question is what Java means by dividing one integer by another.
- The class and main method are the required outer shape of this program
- Each int statement declares a variable and stores a whole number in it
- The division on the line that computes average is the step to predict
What do you think happens?
The program is intended to compute the average of 5 and 2. What does it print?
Reveal answer
3
The sum is 7, and 7 divided by 2 is evaluated with integer division in Java, which keeps only the whole-number part, so the result is 3. The program is valid, so it compiles and runs, but its meaning gives a different answer than the average the author intended.
Following the Values Line by Line
The fastest way to understand why the program printed 3 is to follow the variables one statement at a time. Each statement changes the state of the program, meaning the set of values the variables hold, and the next statement reads whatever state the previous statements left behind. Tracing the program is a matter of writing down that state after every line.
Tracing the average program
Determine the value stored in average and the printed output of the AverageDemo program.
- 1Declare a
a is created and holds 5.
- 2Declare b
b is created and holds 2.
- 3Compute sum
The expression a + b reads the current values 5 and 2, producing 7, which is stored in sum.
- 4Compute average
The expression sum / 2 reads sum, which is 7, and divides it by the integer 2. Under Java's meaning rules for integer division, the fractional part is dropped, so average holds 3.
- 5Print
println prints the current value of average, which is 3.
The program prints 3, not the intended 3.5.
Form Versus Meaning in a Java Program
A useful way to hold two ideas apart is to ask two different questions about the same piece of code. The first question is whether the text is written in a form the language accepts. The second is what the program does once it runs, and whether that behavior matches what you wanted. The first question is about the rules of the language's form. The second is about the rules that give the program its meaning.
Getting the form of a program right is necessary, but it is not sufficient. A program has to mean the right thing, and its meaning is governed by its own set of rules. Those rules are what we call semantics.
When Valid Code Gives the Wrong Answer
The average program is a clear case of valid code with a wrong answer. Nothing in its shape is broken. The compiler accepts every line, and the program runs to completion. The only sign of trouble is the number it prints, which is why correctness has to be judged against intent rather than against whether the code compiles.
The same reasoning applies to any division of two whole numbers. Whether the values came from a calculation, a loop, or a user, the operation's meaning stays the same. Only when you know that rule can you predict that the result will be 3 and not 3.5.
Correcting the Meaning Without Changing the Shape
Once you have found where the meaning diverges from your intent, the fix is usually a change to the expression, not a change to the program's overall structure. If you want the average to keep its fractional part, the operands of the division must produce a non-integer result. Changing the divisor to the decimal literal 2.0 makes the division a floating-point operation, and the result becomes 3.5.
int sum = a + b;
int average = sum / 2;
System.out.println(average);average holds 3 and prints 3
int sum = a + b;
double average = sum / 2.0;
System.out.println(average);average holds 3.5 and prints 3.5
Notice that the corrected program is still valid Java with the same overall structure. Only the meaning of one expression has changed, which is the point of the source's distinction. Writing the program correctly requires knowing what each operation means, not only how to write it.
Mistakes That Hide Behind Valid Syntax
Common mistake Assuming that a program which compiles is correct
What it looks likeThe average program compiles and prints 3 without any error message.
Why it failsCompilation checks the form of the text. It does not check whether the output matches what you intended.
Do this insteadDecide the expected result for a chosen input, run the program, and compare the two.
Common mistake Predicting division by reading the symbols rather than the meaning rules
What it looks likeReading sum / 2 as 3.5 because 7 divided by 2 looks like 3.5 on paper.
Why it failsThe result depends on the semantic rule for dividing one integer by another, not on ordinary arithmetic notation.
Do this insteadApply the language's meaning rules to the operands' types before predicting the result.
Common mistake Treating a changed value as if it were a changed form
What it looks likeChanging a variable from an int to a double and expecting the statements to be rewritten in a new style.
Why it failsThe change alters what the expression means, so it changes the behavior even when the surrounding code looks similar.
Do this insteadTrace the variable values after each statement to see exactly how the meaning moved.
Common mistake Forgetting that a valid statement can still store a value you did not expect
Checking Output Against Intent
Good practice centers on meaning. Before you trust a program, decide in advance what result it should produce for a chosen input, then run it and compare. A mismatch tells you that something about the meaning is off, even when every line is valid. Lining up the expected output with the actual output is what reveals the divergence.
Without running it, predict what this program prints, then apply the same meaning rule you used for the average program. int x = 7; int y = 2; System.out.println(x / y);
Hints
- Both x and y are integers, so the division is integer division.
- Integer division keeps only the whole-number part of the quotient.
- Write down the value of x / y before you check the printed line.
Key Takeaways
- Syntax is the form a Java program must take, and semantics is the set of rules that determine what the program means when it runs.
- A program can be syntactically valid and run successfully while still producing a result you did not intend.
- Predicting a program's behavior requires applying the language's meaning rules, such as the rule for dividing one integer by another, not just reading its form.
- Tracing variable values after each statement shows exactly where the meaning diverges from your intent.
- Correctness is judged against intent: decide the expected result in advance, run the program, and compare.