Concepts / Syntax of Java Programs

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.

  • Programming

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.

java
Notes on the code
  • 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?

  • 3.5

  • 3

  • 2.5

  • It does not compile

Reveal answer
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.

a = 5after int a = 5b = 2after int b = 2sum = 7after int sum = a + baverage = 3after int average = sum / 2prints 3System.out.println(average)next statementnext statementnext statementnext statement
After each statement executes, what value does each variable hold, and how does that change the next line's result?
Worked example

Tracing the average program

Determine the value stored in average and the printed output of the AverageDemo program.

  1. 1
    Declare a

    a is created and holds 5.

  2. 2
    Declare b

    b is created and holds 2.

  3. 3
    Compute sum

    The expression a + b reads the current values 5 and 2, producing 7, which is stored in sum.

  4. 4
    Compute 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.

  5. 5
    Print

    println prints the current value of average, which is 3.

Result

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.

Valid Java textaccepted by the compiler(5 + 2) / 2an expression with ameaningStatements end withsemicolonsrequired by the formInteger divisionthe rule that gives theresultCompiles withouterrorform is correctResult is 3compared with intended 3.5
What is the difference between the rules that decide whether code is legal form and the rules that decide what the code does when it runs?
Key point

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.

Before
int sum = a + b;
int average = sum / 2;
System.out.println(average);

average holds 3 and prints 3

After
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 like

    The average program compiles and prints 3 without any error message.

    Why it fails

    Compilation checks the form of the text. It does not check whether the output matches what you intended.

    Do this instead

    Decide 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 like

    Reading sum / 2 as 3.5 because 7 divided by 2 looks like 3.5 on paper.

    Why it fails

    The result depends on the semantic rule for dividing one integer by another, not on ordinary arithmetic notation.

    Do this instead

    Apply 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 like

    Changing a variable from an int to a double and expecting the statements to be rewritten in a new style.

    Why it fails

    The change alters what the expression means, so it changes the behavior even when the surrounding code looks similar.

    Do this instead

    Trace 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.

EASY

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.