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.

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.

From HelloWorld.java to the outputThree steps: you write HelloWorld.java, javac compiles it to HelloWorld.class (bytecode) or reports errors, and java starts the JVM, which looks for main and produces the output. Warning: the file is named after the public class.You writeHelloWorld.javatext (sourcecode)javac compilesHelloWorld.classbytecode(or errors)java runsJVMlooks for main→ output$ javac HelloWorld.java$ java HelloWorldThe file is named after the public class, letter by letter:public class HelloWorld → HelloWorld.java (helloWorld.java will not compile)Shortcut since Java 11: java HelloWorld.java compiles in memory and runs (no .class)
javac translates your text into bytecode and java runs it. If javac reports errors there is no .class and nothing to run.

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

PythonJava
print("Hello") loose in the fileInside a method, inside a class
The program starts on the first lineThe program starts in main
Blocks are marked by indentationBlocks are marked by braces { }
Each line is a statementEach statement ends in ;
You don’t declare typesYou 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).

ClassFileCompiles?
public class HelloWorldHelloWorld.javaYes
public class HelloWorldhelloWorld.javaNo
public class HelloWorldHelloworld.javaNo
public class HelloWorldhello_world.javaNo

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.

Anatomy of the minimal programThe HelloWorld program: the class wraps the main method, which wraps the println statement ending in a semicolon. Below, what each word of the signature means: public, static, void, main and String[] args.public class HelloWorld {public static void main(String[] args) {System.out.println("Hello world");}}class bracesmain braces; end of statementpublicthe JVM can see itstaticno objects neededvoidreturns nothingmainexact nameString[] argsarguments
One box inside another: braces open and close each block, and the semicolon ends each statement.

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

WordWhat it meansIf you change it…
publicAnyone can call it; the JVM calls it from outside your classThe JVM can’t find it
staticIt belongs to the class, not to an object: it can be called without creating one“Main method is not static”
voidIt returns nothing (like a Python function without return)It’s not the main the JVM is looking for
mainThe name the JVM looks for, in lower caseMain or start won’t do
String[] argsAn array of texts with the command-line argumentsWith 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:

PieceWhat it is
SystemA Java class that is always available (no import needed)
outStandard output: the screen (the console)
printlnPrints 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’s print().
  • print("…") prints without a new line: it’s Python’s print(…, 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.

PlaceholderForExamplePrints
%sText (String)printf("%s", "Laura")Laura
%dWhole number (int)printf("%d", 19)19
%.2fDecimal with 2 placesprintf("%.2f", 8.75)8.75
%fDecimal with 6 placesprintf("%f", 8.75)8.750000
%nNew line
%%A %printf("100%%")100%
%8.2f / %-8.2fWidth 8, right / left aligned[ 8.75] / [8.75 ]
%05dPads with zerosprintf("%05d", 42)00042

Two details worth looking at in the output:

  • The decimal separator. printf uses the computer’s language. On a computer set to Spanish (or French, German…) %.2f prints 8,75, with a comma. Passing java.util.Locale.US as 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. %.1f of 8.75 gives 8.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 writeIt prints
\nA new line
\tA 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
Concatenating with +Three expressions: "Credits: " + 6 + 6 gives "Credits: 66" because the 6 is first stuck onto the text; with brackets it gives "Credits: 12"; and 6 + 6 + " credits" gives "12 credits" because it adds the numbers first.Java evaluates + from left to right"Credits: " + 6 + 61) "Credits: " + 6text + number = text2) "Credits: 6" + 6"Credits: 66""Credits: " + (6 + 6)1) (6 + 6)adds numbers2) "Credits: " + 12"Credits: 12"6 + 6 + " credits"1) 6 + 6adds numbers2) 12 + " credits""12 credits"
As soon as there is a String on the left, every + after it sticks instead of adding. Brackets change the order.

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' gives 131: 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

  1. Create the file with the exact class name: StudentCard.java.
  2. Paste the code and save.
  3. Click Run above main (added by the Extension Pack for Java) or open the terminal and type javac StudentCard.java and java StudentCard.
  4. 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 messageWhat it means
';' expectedA semicolon is missing (on that line or the one above)
class X is public, should be declared in a file named X.javaThe file isn’t named like the class
reached end of file while parsingA closing brace is missing
cannot find symbolA misspelt name (method, class or variable)
package system does not existA capital letter written in lower case
unclosed string literalYou 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:

  1. The red arrow starts on the first line of main, not on the class line: that’s the front door.
  2. After print("Laura "), look at the output panel: “Laura ” waits on the same line until the next println.
  3. With "Credits: " + 6 + 6 the output shows 66; on the next line, with brackets, 12.
  4. Look at how the printf with %.2f comes out: 7.46 with a point. On a computer set to Spanish it would print 7,46.

Quick summary

ConceptRule
ClassAll code goes inside public class Name { … }
FileNamed after the public class: Name.java
Entry pointpublic static void main(String[] args), exactly
BlocksBraces { }; indentation is just for reading
StatementsEnd in ;
Outputprintln (new line), print (no new line), printf (with placeholders)
Text+ sticks from left to right; brackets change the order
Runningjavac Name.java and java Name

Three ideas to keep:

  1. 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 ({ }).
  2. The file is named after the class, letter by letter.
  3. 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.

Next step: practiceJava syntax practice — the enrolment card, the FP2 timetable and a receipt with three errors (to stop fearing javac)

Did this article help you? Here is how you can support SergioLearns →

Sigue aprendiendo

Leave a Reply

Your email address will not be published. Required fields are marked *