Java Syntax
Java syntax is the set of rules that determine how you write valid Java code: where semicolons go, how classes and methods are structured, how blocks are opened and closed, and how names must be formed. Every Java program you will ever write, from a five-line script to a million-line application, is built from the same small set of syntactic building blocks described in this lesson. Getting comfortable with this structure early means every later topic – variables, loops, classes, objects – will feel like a small addition to something you already know, rather than a new language.
Overview: How Java Syntax Works
Java source code is plain text saved in a file with a .java extension. Before any of it can run, it passes through two stages: compilation and execution. The javac compiler reads your source file, checks it against Java’s grammar and type rules, and, if everything is valid, emits a .class file containing platform-independent bytecode. The Java Virtual Machine (JVM) then loads that bytecode, verifies it for safety, and executes it – either by interpreting instructions one at a time or by using the Just-In-Time (JIT) compiler to translate frequently used code paths into native machine instructions for speed.
Because of this two-stage pipeline, Java syntax is enforced at two levels. First, the compiler enforces grammar: every statement must end in a semicolon, every opening brace { must have a matching closing brace }, and code must be organized into classes. Second, Java enforces semantic rules layered on top of that grammar: variables must be declared with a type before use, and that type is checked at compile time, since Java is statically typed – unlike Python or JavaScript, which check types only while the program is running.
A Java program is fundamentally an ordered collection of classes. Nothing – not even a single println – can exist outside a class. Each class describes fields (data) and methods (behavior). When you run a Java program, the JVM looks for a method with one very specific signature, public static void main(String[] args), inside the class you named on the command line, and it begins executing statements from the first line inside that method’s block. Everything you write follows a nested block structure: the file contains a class, the class contains methods, and methods contain statements, some of which – like if, for, and while – themselves contain nested blocks of their own.
Java is case-sensitive throughout: Main, main, and MAIN are three completely different identifiers to the compiler. Whitespace (spaces, tabs, and newlines) exists only to separate tokens – the compiler does not care how you indent or how many blank lines you leave, but consistent formatting matters enormously for humans reading your code. Java supports three comment styles: // single line, /* multi-line */, and /** Javadoc */ for generating documentation. Comments are stripped out before compilation and have zero effect on the compiled program.
Syntax
Every Java source file follows the same overall skeleton:
[package statement;]
[import statements;]
public class ClassName {
// fields
type fieldName;
// methods
returnType methodName(parameterType parameterName) {
// statements
}
public static void main(String[] args) {
// program entry point
}
}
| Element | Purpose | Example |
|---|---|---|
| Package statement | Declares which package the file belongs to; must be the first non-comment line if present | package com.example; |
| Import statement | Brings another class into scope so you can use its short name | import java.util.Scanner; |
| Class declaration | Defines a class; a public class’s name must match the file name exactly | public class Main { } |
| Method | A named, reusable block of behavior with a return type and parameters | static int add(int a, int b) { return a + b; } |
| Statement | A single instruction, always terminated with a semicolon | int x = 5; |
| Block | Zero or more statements grouped with curly braces | { int x = 1; x++; } |
Identifiers and Keywords
An identifier is any name you choose for a class, method, variable, or field. Java identifiers must start with a letter, underscore _, or dollar sign $, followed by any combination of letters, digits, underscores, or dollar signs. Identifiers cannot start with a digit and cannot be one of Java’s reserved keywords (class, public, static, void, int, if, for, return, and roughly fifty others) – those words are permanently reserved by the language grammar and will cause a compile error if used as names.
The compiler does not enforce naming style, but the entire Java ecosystem follows the same conventions: class names use PascalCase (BankAccount), method and variable names use camelCase (calculateTotal), and constants declared with final use UPPER_SNAKE_CASE (MAX_SIZE). Following these conventions makes your code instantly readable to any other Java developer.
Examples
Example 1: The Basic Structure
public class Main {
public static void main(String[] args) {
// A single Java statement ends with a semicolon
System.out.println("Java syntax basics");
int age = 25;
System.out.println("Age: " + age);
}
}
Output:
Java syntax basics
Age: 25
This is the smallest complete Java program that does something useful. The public class Main must live in a file named Main.java. Inside it, main is the method the JVM calls first. Each line inside the block ends with a semicolon, and the block itself is delimited by the outer pair of curly braces.
Example 2: Case Sensitivity and Blocks
public class Main {
public static void main(String[] args) {
int score = 10;
int Score = 20;
System.out.println("score = " + score);
System.out.println("Score = " + Score);
if (score < Score) {
System.out.println("score is less than Score");
} else {
System.out.println("score is not less than Score");
}
}
}
Output:
score = 10
Score = 20
score is less than Score
Because Java is case-sensitive, score and Score are two entirely separate variables occupying separate memory locations - the compiler never confuses them. This example also shows a nested block: the if and else bodies are each their own block of statements, delimited by their own braces, living inside the outer main block.
Example 3: Methods, Parameters, and Constants
public class Main {
static int square(int n) {
return n * n;
}
public static void main(String[] args) {
final double PI = 3.14159;
int result = square(6);
System.out.println("PI = " + PI);
System.out.println("6 squared = " + result);
}
}
Output:
PI = 3.14159
6 squared = 36
This example introduces a second method, square, declared outside main but inside the same class. Its syntax follows the general method form: a return type (int), a name, a parenthesized parameter list (int n), and a block containing a return statement. The final keyword before PI makes that variable a constant - attempting to assign it a new value later would be a compile error.
Under the Hood: From Source to Running Program
- You save your source code in a file, for example
Main.java. The file name must exactly match the name of the public class it contains, including letter case. - Running
javac Main.javatokenizes the text into keywords, identifiers, literals, and operators, then parses those tokens into a tree structure according to Java's grammar. Syntax errors - a missing semicolon, an unmatched brace - are caught at this stage, before any type checking happens. - The compiler then performs semantic analysis: resolving imports, checking that every variable is declared before use, and verifying that types are compatible wherever values are assigned, passed, or returned.
- If every check passes,
javacemitsMain.class, containing JVM bytecode - a compact, platform-independent instruction set, not native machine code. - Running
java Mainstarts the JVM, which loadsMain.classthrough its classloader, runs a bytecode verifier to confirm the file is well-formed and safe, and then locatespublic static void main(String[] args)as the entry point. - The JVM begins executing bytecode instructions, typically on a stack-based interpreter at first; methods that run often are detected as "hot" and compiled to native machine code by the JIT compiler for better performance.
- When
mainreturns, or code callsSystem.exit(), the JVM shuts down and the operating system process ends.
Common Mistakes
1. Forgetting a semicolon
Every statement needs a terminating semicolon. This will not compile:
int total = 10 + 5
System.out.println(total);
The compiler reports something like ';' expected on the line above where the missing semicolon should have been, because it keeps reading tokens looking for a statement terminator that never arrives. The fix is simply to add it back:
int total = 10 + 5;
System.out.println(total);
2. File name does not match the public class name
If a file is named App.java but declares public class Main { }, javac refuses to compile it, reporting something like class Main is public, should be declared in a file named Main.java. Java requires this match because the compiler and classloader both use the file system path to locate a public class by name. The fix is to either rename the file to Main.java, or remove the public modifier if the class doesn't need to be publicly accessible from other files.
3. Mismatched or misplaced braces
Every { needs exactly one matching }. A missing closing brace at the end of a class often produces a confusing error far from the real problem, such as reached end of file while parsing:
public class Main {
public static void main(String[] args) {
System.out.println("Hello");
}
// missing closing brace for the class
Because the compiler only realizes a brace is missing once it runs out of file to read, always add the closing brace immediately after typing the opening one, then fill in the body - most editors and IDEs do this automatically and will visually highlight matching pairs.
Best Practices
- Name the file exactly after the public class it contains, matching letter case precisely.
- Write one statement per line, and always terminate it with a semicolon.
- Always use braces
{ }aroundif,for, andwhilebodies, even single-line ones, to avoid subtle bugs when code is edited later. - Follow naming conventions:
PascalCasefor classes,camelCasefor methods and variables,UPPER_SNAKE_CASEfor constants. - Indent consistently - four spaces per nesting level is Java's de facto convention - so block structure is visually obvious.
- Keep methods short and give them verb-based names that describe what they do, like
calculateTotalorisValid. - Prefer meaningful identifiers over single letters, except for conventional loop counters like
iandj. - Let your IDE or an auto-formatter catch bracket and semicolon mistakes as you type, instead of waiting for the compiler.
Practice Exercises
Exercise 1: The following program has three syntax errors: a missing semicolon, a missing closing brace, and a variable name that illegally starts with a digit. Rewrite it so it compiles and prints all three values.
public class Main {
public static void main(String[] args) {
int 1stNumber = 5
double price = 19.99;
String name = "Java";
System.out.println(1stNumber);
System.out.println(price);
System.out.println(name);
}
Exercise 2: Write a program that defines a method int cube(int n) which returns n * n * n. In main, call it for the numbers 4 and 9 and print each result with a label. Expected output:
4 cubed = 64
9 cubed = 729
Exercise 3: Without writing or running any code, explain in your own words why a file named Calculator.java cannot contain public class MathTools { }, and what error message javac would report if you tried to compile it anyway.
Summary
- Every Java statement ends with a semicolon; related statements are grouped into blocks with curly braces.
- All code lives inside a class; execution always starts at
public static void main(String[] args). - A file may contain only one public class, and it must be named exactly after that class, including case.
- Java is case-sensitive and statically typed - types are checked when you compile with
javac, not while the program runs. - Compiling produces platform-independent
.classbytecode; the JVM verifies and executes that bytecode, optionally JIT-compiling frequently run code for speed. - Reserved keywords can never be used as identifiers; conventional naming (
PascalCase/camelCase/UPPER_SNAKE_CASE) is not compiler-enforced but is essential for readable code.
