Every Java program looks far heavier than the task it performs. Where Python prints a greeting with a single short line and stops, Java wraps that one action inside a class, a method, and an exact signature before it will lift a finger. That ceremony is the most common reason newcomers walk away from the language in their first week.
The move that changes everything is to stop reading the boilerplate as noise. Each layer exists because Java was designed for programs that swell into hundreds of files and run for a decade, and at that scale the structure that feels absurd at five lines is exactly what keeps a sprawling codebase readable. Nothing here is decoration. This lesson names every piece of the outline, so that by the end the shape is automatic and the error messages you meet next start to read in plain English.
flowchart TD CLASS["public class Main"] --> METH["public static void main(String[] args)"] METH --> ST1["System.out.println(...);"] METH --> ST2["System.out.println(...);"] style CLASS fill:#c2410c,color:#fff style METH fill:#c2410c,color:#fff
Anatomy of a minimal program
Here is the smallest Java program that produces visible output, with each part named:
public class Main {
public static void main(String[] args) {
System.out.println("Hello, world");
}
}
public class Maindeclares a class calledMain. By Java's rule, the file must be namedMain.java, because the public class and its file share a name.public static void main(String[] args)is the entry point. The JVM looks for this exact signature and starts running from there.System.out.println("...")writes one line to the console and then moves down to the next line.- A semicolon ends every statement; drop one and the compiler stops, usually flagging the line after the real mistake.
- Braces group a block: the class body holds the method, and the method body holds its statements.
Reading what the compiler tells you
When compilation fails, the compiler prints a file name and a line number, but it often points one line below the real mistake. It only realises a statement is unfinished when the next one begins, so a missing semicolon on line 4 is reported at line 5. Read the message, then look up a line.
You can also leave notes for yourself with //, which begins a comment: everything from there to the end of the line is ignored by the compiler. Comments explain intent to the next reader, who is very often you, three months later.
What every word of main is for
That signature looks arbitrary; it is not. Each keyword earns its place, and knowing them turns cryptic launch errors into obvious ones.
publiclets the JVM reach this method from outside the class. Make it private and the file compiles, but nothing can start it.staticmeans the method belongs to the class itself, so the JVM can invoke it before any object exists. Withoutstatic, Java would need an object to runmainfirst, and at launch no object exists yet.voiddeclares that the method returns nothing; it simply runs.mainis the exact name the JVM searches for. Rename it tostartand the code compiles, then sits dead.String[] argscollects the command-line arguments as an array of text. A program can ignore them, but it cannot drop the parameter.
Change any one and the file still compiles, but fails at launch: the JVM cannot find a usable entry point.
flowchart TD J["JVM loads Main.class"] --> S["Looks for one exact method:<br/>public static void main(String[] args)"] S -->|found| R["Starts here, runs the first statement"] S -->|not found| E["Refuses to start:<br/>no usable main method"] style R fill:#3776ab,color:#fff style E fill:#b45309,color:#fff
Braces define blocks; whitespace does not
If you are coming from Python, this is the rule that will save you the most confusion. Python uses indentation to decide which lines belong together; Java uses braces and ignores indentation entirely. You could flatten the whole program onto one line and it would still compile, because the compiler tracks braces, not spaces.
Indentation in Java exists purely for the human reading it. The universal convention is four spaces per nested level, matching how deep the braces sit, so the eye can see the structure at a glance. The compiler does not enforce that convention; other programmers do.
public class Main {
public static void main(String[] args) {
String language = "Java";
int version = 21;
System.out.println("Language: " + language);
System.out.println("Version: " + version);
System.out.println("Ready to learn.");
System.out.println("Let's begin.");
}
}
Printing with println and print
System.out.println writes its argument and then advances to a fresh line; System.out.print writes the same text and stays put, so the next call continues exactly where this one ended. Reach for println when each value deserves its own line, and for print when you want to assemble one line from several pieces.
Both accept a string, a number, or several values joined with +. When + has text on one side, Java converts the other side to text and stitches them together, so "Version: " + 21 prints Version: 21. That stitching is called concatenation, and it is convenient enough to hide a trap you will meet shortly.
flowchart TD P["System.out.print(x)"] --> PO["writes x, then stays on this line"] L["System.out.println(x)"] --> LO["writes x, then drops to the next line"] style PO fill:#b45309,color:#fff style LO fill:#3776ab,color:#fff
public class Main {
public static void main(String[] args) {
System.out.print("Hello");
System.out.print(", ");
System.out.println("world");
System.out.println("Line two");
}
}
What does this program print? Read it carefully and type the exact output (four lines).
public class Main {
public static void main(String[] args) {
String language = "Java";
int version = 21;
System.out.println("Language: " + language);
System.out.println("Version: " + version);
System.out.println("Ready to learn.");
System.out.println("Let's begin.");
}
}
Each
printlnprints one line.+joins the string literal with the variable value.There are four
printlncalls, so there are four lines of output.
What is the correct signature for the method the JVM calls to start a program?
The JVM requires exactly public static void main(String[] args). Any deviation — missing static, wrong return type, wrong parameter type — and the program will compile but fail to run with NoSuchMethodError: main.
println or print? Read carefully and predict the exact output (two lines).
public class Main {
public static void main(String[] args) {
System.out.print("Hello");
System.out.print(", ");
System.out.println("world");
System.out.println("Line two");
}
}
printdoes not add a newline, so the first three calls share a single line.Only
printlnmoves the cursor down.Two
printlncalls mean two visible lines in total.
Concatenation check. Predict all three lines. The order of the + operations matters.
public class Main {
public static void main(String[] args) {
int a = 1;
int b = 2;
System.out.println("Sum: " + a + b);
System.out.println("Sum: " + (a + b));
System.out.println(a + b + " is the sum");
}
}
+runs left to right. Once a string is involved, the rest is joined as text.Parentheses force the arithmetic to happen first.
In the last line, the two numbers are added before they ever meet a string.
You save this program as Main.java and compile it with javac Main.java. What happens?
public class Hello {
public static void main(String[] args) {
System.out.println("Hi");
}
}
Java requires a public class to live in a file whose name matches the class. public class Hello inside Main.java fails to compile with a message naming the mismatch. Rename the file to Hello.java, or rename the class to Main, so the two agree.
Recap
- A Java program is a class containing a method called
main; execution starts there and nowhere else. - The signature
public static void main(String[] args)is exact —public,static,void, the namemain, and theString[]parameter are all required, or the program compiles but never starts. System.out.printlnprints a line and advances;System.out.printprints without advancing.+concatenates left to right, so"Sum: " + 1 + 2givesSum: 12; use parentheses to add first.- Semicolons end statements, braces define blocks, and capitalisation must be exact.
Next you will turn this skeleton into something reusable by giving it variables and types — the named slots that hold a program's data.