Java syntax — the class, main, println and the semicolon explained line by line (for anyone coming from Python)
In my first Java lab I copied the “Hello world” from the board letter by letter and it still wouldn’t compile. Twenty minutes staring at the code until the lecturer came by, looked at the editor tab and said: “your file is called helloWorld.java and your class HelloWorld“. One capital letter. In Python that would never have mattered. In Java it’s the first rule you have to learn by heart, and it’s not the only one that catches you out if you come from FP1.
This article is Java syntax from the very first line: why everything lives inside a class, what each word of public static void main(String[] args) means, what braces and semicolons are for, how to print with println, print and printf, how to join text with + (and why you sometimes get 66 instead of 12) and how to read the compiler’s errors. Every program has been compiled with Java 21 and the outputs are real. The example that goes with us is the card of an FP2 student (made-up data).
If you don’t have Java installed yet, start with the guide to installing Java on Windows. And if you’ve just finished Python, the last topic was Python LinkedList: the references you saw there work exactly the same in Java.
Table of Contents
The minimal Java program, every line explained
This is the exact equivalent of print("Hello world") in Python:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello world");
}
}
Five lines for a single useful statement. It’s not that Java is harder: it’s that everything is explicit. Python decides lots of things for you (where the program starts, where each statement ends, what type each thing has); Java asks you to write them. Running it takes two steps, compiling and running. This is how it looks in the terminal:
$ javac HelloWorld.java $ ls HelloWorld.class HelloWorld.java $ java HelloWorld Hello world $ java HelloWorld.java Hello world
javac (the compiler) reads HelloWorld.java and, if there are no errors, creates HelloWorld.class: the bytecode, a translation that the Java virtual machine (the JVM) understands. java HelloWorld starts the JVM with that class (note: without .class). The last line is a shortcut since Java 11: java HelloWorld.java compiles in memory and runs, without leaving a .class. It’s handy for one-file programs, but in the labs you want to see both steps.
Why Java needs a class for everything
In Python you could write loose code: a variable here, a print there. Java doesn’t allow it: all code lives inside a class. That’s why even the smallest program starts with public class HelloWorld {.
| Python | Java |
|---|---|
print("Hello") loose in the file | Inside a method, inside a class |
| The program starts on the first line | The program starts in main |
| Blocks are marked by indentation | Blocks are marked by braces { } |
| Each line is a statement | Each statement ends in ; |
| You don’t declare types | You declare the type of everything (we’ll see it in variables) |
Why? Java was born in 1995 for large programs where everything is organised in classes (the object-oriented programming you saw in FP2 with Python). There is no “classless mode”. For now, keep the rule: before you write a line, you need a class to hold it.
public before class means the class is visible from anywhere. All your FP2 programs will start like this: public class ClassName.
The filename rule: the most important of all
The .java file must be named exactly like the public class, with the same capital letters. This is what happened in my first lab: the file helloWorld.java with the class HelloWorld inside.
$ javac helloWorld.java
helloWorld.java:1: error: class HelloWorld is public, should be declared in a file named HelloWorld.java
public class HelloWorld {
^
1 error
The message says it all: “class HelloWorld is public, should be declared in a file named HelloWorld.java”. The little arrow ^ points at the class name. The fix is to rename the file (or the class, but then everything that uses it changes).
| Class | File | Compiles? |
|---|---|---|
public class HelloWorld | HelloWorld.java | Yes |
public class HelloWorld | helloWorld.java | No |
public class HelloWorld | Helloworld.java | No |
public class HelloWorld | hello_world.java | No |
On Windows, File Explorer doesn’t distinguish upper and lower case, so it may look as if the file “already has the right name”. Check the exact name in the VS Code tab or with dir in the terminal.
Curly braces: how Java marks blocks
In Python, what’s inside something is marked by indentation. In Java it’s marked by braces: { opens a block and } closes it. The minimal program has two blocks, one inside the other: the class and main.
Indentation in Java means nothing to the compiler: it’s only there for people to read. This compiles just as well (even if it’s unreadable):
public class HelloWorld{public static void main(String[] args){System.out.println("Hello world");}}
What does matter is that every brace you open gets closed. If one is missing, javac reaches the end of the file still waiting for a }:
public class Brace {
public static void main(String[] args) {
System.out.println("I'm missing a brace");
}
Brace.java:4: error: reached end of file while parsing
}
^
1 error
“reached end of file while parsing”: it got to the end of the file while still reading. The line it points to (4) is the last one with something on it: the real error is that a brace is missing after it.
In VS Code, Shift + Alt + F formats the file. If after formatting the indentation looks odd, it’s almost always a brace too many or too few just before the crooked part.
The semicolon: why every statement ends in ;
In Python, the end of the line is the end of the statement. In Java a statement ends when a semicolon arrives. That’s why you can split a long statement over several lines, and why forgetting it is the number one error for anyone coming from Python:
public class Semicolon {
public static void main(String[] args) {
System.out.println("Hello")
System.out.println("Goodbye");
}
}
Semicolon.java:3: error: ';' expected
System.out.println("Hello")
^
1 error
';' expected: it was expecting a semicolon. The little arrow ^ points right after the ), where it should be. Sometimes javac flags the next line, because it doesn’t notice the problem until the next statement starts: if the flagged line looks right, check the one above.
What takes a semicolon? Statements: System.out.println(...);, and later declarations (int n = 5;) and returns. What doesn’t? Lines that open or close blocks: public class HelloWorld {, }, public static void main(String[] args) {.
The main method: the program’s front door
Python runs a file from top to bottom. Java doesn’t: when you type java HelloWorld, the JVM looks in the class for a method with this exact signature and starts there:
public static void main(String[] args)
If you change anything, the class compiles, but the JVM doesn’t recognise it as a program. Let’s try two typical changes. Without static:
public class NoStatic {
public void main(String[] args) {
System.out.println("Will I get printed?");
}
}
Error: Main method is not static in class NoStatic, please define the main method as: public static void main(String[] args)
And with String args instead of String[] args:
Error: Main method not found in class NoBrackets, please define the main method as: public static void main(String[] args) or a JavaFX application class must extend javafx.application.Application
Both compile (javac doesn’t complain: they’re valid methods), but java can’t find the front door.
What each word of public static void main(String[] args) means
| Word | What it means | If you change it… |
|---|---|---|
public | Anyone can call it; the JVM calls it from outside your class | The JVM can’t find it |
static | It belongs to the class, not to an object: it can be called without creating one | “Main method is not static” |
void | It returns nothing (like a Python function without return) | It’s not the main the JVM is looking for |
main | The name the JVM looks for, in lower case | Main or start won’t do |
String[] args | An array of texts with the command-line arguments | With String args, “Main method not found” |
Why static? When the program starts there are no objects yet. The JVM needs to call main directly on the class, and only static methods allow that. In the class topics you’ll see many methods without static, but main always has it.
Recent versions of Java (Java 25 makes it final) let you write a much shorter void main(). FP2 uses Java 21 and the full signature, which is what the exam will ask for.
Upper and lower case
Java is case-sensitive in everything: System is not system, String is not string, main is not Main.
public class Capitals {
public static void main(String[] args) {
system.out.println("Hello");
}
}
Capitals.java:3: error: package system does not exist
system.out.println("Hello");
^
1 error
“package system does not exist”: as system starts with a lower-case letter, Java thinks it’s the name of a package (a folder of classes) and can’t find it. By convention, classes start with a capital (System, String, HelloWorld) and methods and variables with a lower-case letter (main, println).
Comments in Java
Java has three kinds. The first two are equivalent to Python’s:
// Single-line comment (Python's #) /* Multi-line comment: everything between /* and */ is ignored */ /** * Documentation comment (Javadoc): goes right before a class or a method * and Java's tools use it to generate documentation. */
In FP2 you’ll mostly use //. You’ll see /** */ at the top of the lecturer’s classes and in this very article, in the complete card.
Output: System.out.println and friends
In Python it’s print(). In Java it’s System.out.println(). Longer, but each piece makes sense:
| Piece | What it is |
|---|---|
System | A Java class that is always available (no import needed) |
out | Standard output: the screen (the console) |
println | Prints and starts a new line (print line) |
There are three ways to print:
public class Output {
public static void main(String[] args) {
System.out.println("Hello"); // prints and starts a new line
System.out.println("World");
System.out.print("Hello"); // no new line
System.out.print(" World");
System.out.println(); // just the new line: closes the line
System.out.println("---");
System.out.printf("%s is %d years old%n", "Laura", 19);
System.out.printf("Grade: %.2f | %.1f | %f%n", 8.75, 8.75, 8.75);
System.out.printf("[%8.2f] [%-8.2f]%n", 8.75, 8.75);
System.out.printf("[%5d] [%-5d] [%05d]%n", 42, 42, 42);
System.out.printf("100%% attendance%n");
System.out.printf(java.util.Locale.US, "Always a point: %.2f%n", 8.75);
}
}
Output:
Hello World Hello World --- Laura is 19 years old Grade: 8.75 | 8.8 | 8.750000 [ 8.75] [8.75 ] [ 42] [42 ] [00042] 100% attendance Always a point: 8.75
println("…")prints and starts a new line: it’s Python’sprint().print("…")prints without a new line: it’s Python’sprint(…, end=""). That’s why “Hello” and ” World” come out on the same line.println()with nothing prints just the new line: it closes the line or leaves an empty one.
Formatted output: printf
printf is the equivalent of f-strings: a text with placeholders and, after it, the values that go into them, in order.
| Placeholder | For | Example | Prints |
|---|---|---|---|
%s | Text (String) | printf("%s", "Laura") | Laura |
%d | Whole number (int) | printf("%d", 19) | 19 |
%.2f | Decimal with 2 places | printf("%.2f", 8.75) | 8.75 |
%f | Decimal with 6 places | printf("%f", 8.75) | 8.750000 |
%n | New line | ||
%% | A % | printf("100%%") | 100% |
%8.2f / %-8.2f | Width 8, right / left aligned | [ 8.75] / [8.75 ] | |
%05d | Pads with zeros | printf("%05d", 42) | 00042 |
Two details worth looking at in the output:
- The decimal separator.
printfuses the computer’s language. On a computer set to Spanish (or French, German…)%.2fprints 8,75, with a comma. Passingjava.util.Locale.USas the first argument forces the point whatever the language: that’s the last line. If an exam statement shows the expected output with a comma and yours has a point (or the other way round), your program isn’t wrong: it’s the locale. - Rounding.
%.1fof8.75gives8.8: it rounds, it doesn’t cut.
The placeholder must match the type. printf("%d", 7.5) compiles, but when it runs it throws IllegalFormatConversionException (you’ll see it in the exercises). For decimals, %f; for whole numbers, %d.
Use %n and not \n inside printf: %n puts the right line ending for each system (Windows uses a different one from Linux).
Escape sequences
Some characters can’t be written as they are inside quotes. You write them with a backslash in front, just like in Python:
public class Escapes {
public static void main(String[] args) {
System.out.println("Line 1\nLine 2"); // \n starts a new line
System.out.println("Monday\tFP2\tIC2"); // \t jumps to the next tab stop
System.out.println("Said: \"it compiles now\""); // \" puts a quote inside the text
System.out.println("Folder: C:\\FP2\\Topic1"); // \\ puts a backslash
}
}
Output:
Line 1 Line 2 Monday FP2 IC2 Said: "it compiles now" Folder: C:\FP2\Topic1
| You write | It prints |
|---|---|
\n | A new line |
\t | A jump to the next tab stop (columns 8, 16, 24…) |
\" | A double quote inside the text |
\\ | A backslash (Windows paths) |
String concatenation
As in Python, + between texts sticks them together. The difference is that in Java you can stick a number onto a text without converting it: Java converts it for you. And that’s where the trap is.
public class Concatenate {
public static void main(String[] args) {
System.out.println("Credits: " + 6 + 6); // left to right: text + 6 = text
System.out.println("Credits: " + (6 + 6)); // the brackets add first
System.out.println(6 + 6 + " credits"); // here it adds first (12) and then sticks
System.out.println("" + 6 + 6); // start with text: everything is text
System.out.println('A' + 'B'); // two chars are ADDED as numbers
System.out.println("A" + "B"); // two Strings are stuck together
System.out.println("Grade: " + 7.5 + " / " + 10);
System.out.println("Passed: " + true);
}
}
Output:
Credits: 66 Credits: 12 12 credits 66 131 AB Grade: 7.5 / 10 Passed: true
Java evaluates the + signs from left to right:
"Credits: " + 6 + 6: first"Credits: " + 6="Credits: 6"(text). Then"Credits: 6" + 6="Credits: 66"."Credits: " + (6 + 6): the brackets go first, 6 + 6 = 12, and then it’s stuck on:"Credits: 12".6 + 6 + " credits": here the first two are numbers, so it adds (12) and then sticks.'A' + 'B'gives131: with single quotes they’re characters (char), which deep down are numbers (65 and 66). With double quotes,"A" + "B", they’re texts and get stuck together.
Adding inside a text without brackets. If a sum comes out with the numbers “stuck together”, put it in brackets.
The complete structure: everything together
The student’s card, with everything we’ve seen: Javadoc comment, class, main, the three kinds of output, concatenation and single and multi-line comments.
/**
* Card of an FP2 student: the complete structure of a Java program
* with println, print, printf, concatenation and the three kinds of comment.
*/
public class StudentCard {
public static void main(String[] args) {
// println: prints and starts a new line
System.out.println("=== FP2 card ===");
System.out.println(); // empty line
// print: no new line (the last println adds it)
System.out.print("Hello, ");
System.out.print("I'm ");
System.out.println("Laura");
// printf: text with placeholders (%s, %d, %.2f) and %n for a new line
System.out.printf("Degree: %s%n", "GCID");
System.out.printf("Credits: %d ECTS%n", 6);
System.out.printf("Midterm grade: %.2f%n", 7.456);
// concatenation with +: the number becomes text
System.out.println("Group " + 41 + ", room " + "A-12");
System.out.println("Passed? " + (7.456 >= 5));
/* multi-line comment:
Java ignores all of it */
}
}
Output:
=== FP2 card === Hello, I'm Laura Degree: GCID Credits: 6 ECTS Midterm grade: 7.46 Group 41, room A-12 Passed? true
Check each line: println() leaves the empty line; the three print/println calls make “Hello, I’m Laura” on a single line; %.2f rounds 7.456 to 7.46; "Group " + 41 + ", room " + "A-12" sticks everything together as text; and (7.456 >= 5) goes in brackets because it’s a comparison that gives true. The comments don’t appear anywhere.
How to run this program in VS Code
- Create the file with the exact class name:
StudentCard.java. - Paste the code and save.
- Click Run above
main(added by the Extension Pack for Java) or open the terminal and typejavac StudentCard.javaandjava StudentCard. - If there are compilation errors, they’re underlined in red and listed in the Problems panel (
Ctrl + Shift + M).
The messages you’ll see most at the beginning:
| javac message | What it means |
|---|---|
';' expected | A semicolon is missing (on that line or the one above) |
class X is public, should be declared in a file named X.java | The file isn’t named like the class |
reached end of file while parsing | A closing brace is missing |
cannot find symbol | A misspelt name (method, class or variable) |
package system does not exist | A capital letter written in lower case |
unclosed string literal | You forgot to close some quotes |
Common errors in the first programs
The file named differently from the public class (capitals included). You fix it by renaming the file.
Forgetting the ; at the end of a statement, or putting one after { or }.
Changing the main signature. It compiles, but java says it can’t find the main method.
Writing system, string or Main. Java is case-sensitive.
"Total: " + 3 + 4 expecting 7. You get 34: brackets rule.
Watch it step by step in Python Tutor
Python Tutor runs Java too: choose Java in the language dropdown. The program has to be a single public class with main. Paste this one:
public class Tutor {
public static void main(String[] args) {
System.out.println("FP2 card");
System.out.print("Laura ");
System.out.println("Santana");
System.out.println("Credits: " + 6 + 6);
System.out.println("Credits: " + (6 + 6));
System.out.printf("Grade: %.2f%n", 7.456);
}
}
Output:
FP2 card Laura Santana Credits: 66 Credits: 12 Grade: 7.46
What to watch step by step:
- The red arrow starts on the first line of
main, not on the class line: that’s the front door. - After
print("Laura "), look at the output panel: “Laura ” waits on the same line until the nextprintln. - With
"Credits: " + 6 + 6the output shows66; on the next line, with brackets,12. - Look at how the
printfwith%.2fcomes out:7.46with a point. On a computer set to Spanish it would print 7,46.
Quick summary
| Concept | Rule |
|---|---|
| Class | All code goes inside public class Name { … } |
| File | Named after the public class: Name.java |
| Entry point | public static void main(String[] args), exactly |
| Blocks | Braces { }; indentation is just for reading |
| Statements | End in ; |
| Output | println (new line), print (no new line), printf (with placeholders) |
| Text | + sticks from left to right; brackets change the order |
| Running | javac Name.java and java Name |
Three ideas to keep:
- Java asks you to write what Python decides on its own: where the program starts (
main), where each statement ends (;) and what is inside what ({ }). - The file is named after the class, letter by letter.
- Read javac’s errors: they give the file, the line and what was expected, and the little arrow
^points at the spot.
In the Java syntax practice we write three programs from scratch: the enrolment card with printf, the timetable in a text table and a receipt with three errors that we fix round by round. After that come variables in Java, where we’ll finally stop repeating the data on every line.
Did this article help you? Here is how you can support SergioLearns →




What is an operating system — theory with your laptop on a study afternoon, a write() call and a CPU that never rests (and the three programs that weren’t running at the same time)