- Understand the basic structure of a Java program
- Learn essential Java syntax elements through a "Hello World" example
- Grasp the concept and importance of the main method in Java
- Recognize the significance of proper code formatting and syntax rules
Java inherited its syntax from C and C++, which means semicolons, curly braces, and a level of verbosity that surprises anyone coming from Python or JavaScript. That verbosity isn't accidental. When fifty developers are maintaining a codebase with thousands of classes, explicit structure stops being annoying and starts being the thing that keeps the project from collapsing under its own weight.
This lesson dissects the "Hello World" program you wrote previously — not because printing a string is interesting, but because those five lines contain nearly every syntactic rule you'll use for the rest of the course. Package declarations, class definitions, method signatures, statement terminators — it's all there, compressed into the smallest possible example.
The program you wrote in the previous lesson packs a surprising amount of structure into five lines:
package academy.javapro.module2;
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}Python does this with a single print() call. But Java's extra ceremony encodes information the compiler and JVM use for type checking, memory management, and runtime optimization.
The package declaration package academy.javapro.module2; establishes this class's namespace. Packages prevent naming collisions — without them, you can't have both a com.amazonaws.auth.User class and your own User class in the same project. Every package declaration ends with a semicolon.
The class declaration public class HelloWorld defines a type named HelloWorld. Java is object-oriented to its core — you can't write standalone functions. Every method must belong to a class, and the public access modifier means this class is visible to code in other packages.
One constraint catches people off guard: the filename must match the public class name exactly, so this lives in HelloWorld.java. Java enforces that mapping so the compiler can locate source files. The relationship is non-negotiable.
Curly braces {} delimit scope throughout the language. The opening brace after the class name begins the class body; the closing brace terminates it. Indentation isn't enforced by the compiler, but without it, your code becomes unreadable fast. With the class structure in place, the next question is: where does execution actually start?
When you run java academy.javapro.module2.HelloWorld, the JVM needs an entry point — a specific method it can call to kick off your program. That entry point has to look exactly like this:
public static void main(String[] args) {
System.out.println("Hello, World!");
}Every keyword in that signature earns its spot. The method is public because the JVM lives outside your class and needs permission to call in. It's static because no objects exist yet when the program starts — the JVM can't instantiate your class first and then call a method on the instance, so the method has to belong to the class itself. The return type is void because main doesn't return a value; if you need to communicate an exit code, you call System.exit() instead.
The name main isn't a convention — it's a hard requirement. The JVM searches for exactly that name. And String[] args is how command-line arguments reach your program. You can rename the parameter to anything you like (String[] arguments, String[] input), but the type must be String[].
Get any of this wrong and the results are frustrating. Drop the static keyword and the code compiles without complaint, but when you try to run it, the JVM throws an error because it can't find a valid entry point. The compiler won't save you from that one — you just have to know the signature.
When you see System.out.println("Hello, World!"); on screen, the output is obvious. The mechanism behind it is worth understanding.
System is a class from the java.lang package, which Java imports automatically into every file — you never write import java.lang.System. On that class, out is a static field of type PrintStream that points to standard output, meaning your console. So System.out gets you a handle to the console, and println() writes text to it followed by a newline.
The string "Hello, World!" uses double quotes, which marks it as a String literal. This distinction matters more than it might seem. Single quotes create char literals — 'A' is a single character, "A" is a String object. They're fundamentally different types, and mixing them up produces compiler errors that feel cryptic if you're coming from a language that doesn't distinguish the two.
The semicolon at the end terminates the statement. Java uses semicolons the way English uses periods — skip one and the compiler can't tell where your thought ends and the next one begins.
Java enforces strict rules about what counts as a valid identifier. Names must start with a letter, underscore, or dollar sign, followed by any combination of letters, digits, underscores, or dollar signs. Keywords like class, public, and void are reserved and off-limits.
Convention dictates PascalCase for class names: HelloWorld, CustomerRepository, HttpRequestHandler. The compiler won't reject helloworld or hello_world, but violating this convention signals inexperience to anyone reading your code. Java's community treats naming conventions as a shared contract — break the contract, and you make every collaborator's life harder.
Case sensitivity runs deep through the language. System and system are entirely different identifiers. public is a keyword; Public is just a name that means nothing to the compiler. This strictness trips people up at first, but it's actually a feature — typos fail at compile time rather than lurking as runtime bugs.
Whitespace is mostly irrelevant to the compiler. Spaces, tabs, and newlines are interchangeable as token separators, and multiple spaces collapse to one. Most Java codebases standardize on four spaces per indentation level, using whitespace to make logical structure visible.
Missing semicolons are the classic beginner mistake, and they produce misleading error messages. The compiler reports where it noticed the problem, not where you forgot the semicolon. A missing semicolon on line 5 often generates an error pointing at line 6, sending you on a brief hunt.
Mismatched braces break everything downstream. IDEs help by highlighting matching pairs and auto-inserting closing braces, but refactoring — moving code blocks around, extracting methods — can still create mismatches that aren't immediately obvious.
Incorrect capitalization causes "cannot find symbol" errors. Write system.out.println() instead of System.out.println() and the compiler tells you it can't find system. The class doesn't exist with a lowercase 's', and Java won't guess what you meant.
The sneakiest error for beginners is the incomplete main signature. Writing public void main(String[] args) without static compiles cleanly. Nothing looks wrong. But the JVM can't find an entry point, and the program fails at launch. The compiler has no reason to warn you — your method is perfectly valid Java, just not the one the JVM is looking for.
- Java requires every piece of code to live inside a class. The
public classdeclaration defines the type, the filename must match the public class name exactly, and packages provide namespace management through thepackagedeclaration at the top of the file. - The
mainmethod signature is non-negotiable:public static void main(String[] args). It'sstaticbecause the JVM calls it before any objects exist,publicbecause the JVM needs external access, andvoidbecause exit status is communicated throughSystem.exit()rather than a return value. - The print statement
System.out.println()chains together a class (System), a static field (out), and a method call (println). Java automatically importsjava.lang, soSystemis available everywhere without an explicit import statement. - Naming conventions like PascalCase for classes aren't compiler-enforced, but the Java community treats them as a shared contract. Case sensitivity is absolute —
Systemandsystemare different identifiers, and the compiler offers no leniency for near-misses. - Common syntax errors follow predictable patterns: missing semicolons, mismatched braces, wrong capitalization, and incomplete method signatures. The compiler catches most of these at build time, which is one of the core advantages a statically typed language gives you over its dynamically typed counterparts.