Your First Java Program — main Method and System.out.println

8 min read

Every Java program starts with the same handful of lines: a class, a main method, and a System.out.println to prove it ran. There are no top-level scripts in Java — even a one-line program needs that wrapping. This lesson breaks down every keyword you'll see, walks through compiling and running from the terminal, and finishes with a real test summary script you can paste, build, and run.

The minimum Java program

Save this as HelloQA.java:

public class HelloQA {
    public static void main(String[] args) {
        System.out.println("Hello from Java QA!");
    }
}

Compile and run it:

javac HelloQA.java   # produces HelloQA.class
java HelloQA          # NOTE: no .class extension, no .java

Output:

Hello from Java QA!

Three lines of code, but every one of them does work. Read each piece slowly — these are the ingredients of every Java file you'll ever write.

Breaking down each line

public class HelloQA — declares a class named HelloQA. The filename must match the class name exactly: HelloQA.java. If you save it as helloqa.java or Main.java, the compiler refuses to build. This rule catches every beginner once.

public static void main(String[] args) — the entry point. When you run java HelloQA, the JVM looks for exactly this signature and starts there. We'll explain each keyword in chapters 3 and 4, but for now memorise the line. Word by word:

  • public — anyone can call this method (the JVM, in this case).
  • static — belongs to the class, not to an instance. Lets the JVM call it without first creating an object.
  • void — returns nothing.
  • main — the conventional name the JVM looks for.
  • String[] args — an array of command-line arguments. Empty if you don't pass any.

System.out.println("Hello from Java QA!"); — print a line to the console. System.out is the standard output stream; println prints what you give it followed by a newline. The closest JavaScript equivalent is console.log().

{ } and ; — Java uses curly braces to group code into blocks (class body, method body) and semicolons to end every statement. These are not optional — leave a ; off and the compiler refuses to build.

Filename rules — the one that catches everyone

The class declared public must live in a file with the matching name. HelloQA.java must contain public class HelloQA. If you rename the file but not the class (or vice versa), javac fails with:

HelloQA.java:1: error: class Main is public, should be declared in a file named Main.java

This is one of the first errors every beginner hits. The fix is always the same: rename one to match the other.

Compile, then run — the two-step flow

Java is compiled, not interpreted. You always do:

javac HelloQA.java   # source → bytecode (.class file)
java HelloQA          # JVM runs the bytecode

Notice that java HelloQA takes the class name, not a filename. Don't write java HelloQA.class (rejected) and don't write java HelloQA.java (works on Java 11+ as a single-file shortcut, but learn the proper two-step flow first — it's what every build tool actually does). After compilation, your folder contains:

HelloQA.java     # source — what you wrote
HelloQA.class    # bytecode — what the JVM runs

In IntelliJ both steps happen invisibly when you click ▶. Knowing the two-step flow pays off when builds fail in CI and you need to read the error message.

println vs print — the newline difference

There are two methods you'll use constantly:

System.out.print("No newline. ");
System.out.print("Same line.");
System.out.println();  // just prints a newline
System.out.println("New line");
System.out.println("Another");

Output:

No newline. Same line.
New line
Another

print writes the text and stops; println writes the text and a newline. For test summaries you almost always want println.

Printing different types

System.out.println accepts any value Java can convert to a string:

public class TestOutput {
    public static void main(String[] args) {
        System.out.println("Test name: Login Test");   // String
        System.out.println(200);                         // int
        System.out.println(true);                        // boolean
        System.out.println(1.25);                        // double
        System.out.println("Status: " + 200 + " OK");   // concatenation
    }
}

Output:

Test name: Login Test
200
true
1.25
Status: 200 OK

The + operator joins strings with anything. When one side is a string, Java converts the other side to a string automatically — that's how "Status: " + 200 becomes "Status: 200". We'll cover this properly in lesson 4.

Comments — code for humans

Three styles of comment, exactly like in JavaScript:

// Single-line comment
 
/*
 * Block comment.
 * Useful for longer notes
 * across several lines.
 */
 
/**
 * Javadoc — a special block that documentation tools
 * read to generate API docs. Used on classes and methods.
 * @param args command-line arguments
 */
public static void main(String[] args) {
    // Print a friendly greeting
    System.out.println("Hello!");
}

The Javadoc form (with the extra * after the opening /*) is conventional on every public class and method in serious Java code. We'll write Javadoc for our test utilities later.

Case sensitivity and semicolons

Two rules that bite beginners daily:

  1. Java is case-sensitive. String is not string. System is not system. println is not Println. Mistyped capitals are the most common compile error after missing semicolons.
  2. Every statement ends with ;. Unlike JavaScript where they're optional, Java requires them. Forget one and the compiler points at the line: error: ';' expected.

A real QA example — a test summary

A program that prints a nightly run summary — exactly the kind of utility you'd write in your first month on the job. Save as NightlySummary.java:

public class NightlySummary {
    public static void main(String[] args) {
        int passed = 28;
        int failed = 4;
        int skipped = 2;
        int total = passed + failed + skipped;
        double passRate = (passed * 100.0) / total;
 
        System.out.println("=== Nightly Test Run ===");
        System.out.println("Total:   " + total);
        System.out.println("Passed:  " + passed);
        System.out.println("Failed:  " + failed);
        System.out.println("Skipped: " + skipped);
        System.out.println("Pass rate: " + passRate + "%");
        System.out.println("========================");
    }
}

Compile and run:

javac NightlySummary.java
java NightlySummary

Output:

=== Nightly Test Run ===
Total:   34
Passed:  28
Failed:  4
Skipped: 2
Pass rate: 82.35294117647058%
========================

That output isn't pretty (the pass rate has too many decimals), but it works. Formatting numbers properly is a chapter-3 topic; for now, the program runs end to end and that's the whole win.

About the boilerplate

Yes, Java needed 3 lines of wrapping (class, main, braces) just to print "hello." JavaScript needs zero; Python needs zero. People sometimes complain about this. Don't.

The wrapping is the trade-off for type safety, IDE tooling, and large-codebase navigation. Once your test framework has 200 classes, the structure becomes the thing that holds the project together. You'll come to appreciate that every test class declares its public surface explicitly — no guessing at what's exported, no undocumented globals.

Match each line to its job

Each line of HelloQA.java does a specific job

Match each piece of the program to what it does.

  • public class HelloQA
  • public static void main(String[] args)
  • System.out.println("...");
  • { ... }
  • ;

 

⚠️ Common mistakes

  • Filename doesn't match the class name. public class HelloQA must live in HelloQA.java. Saving it as Hello.java or helloqa.java makes the compile fail. Pick a name and keep them in sync.
  • Forgetting semicolons. Every statement ends with ;. Java is strict — JavaScript will sometimes guess; Java never does. The error message is always ';' expected and points at the line just after the missing one (because that's where the compiler noticed).
  • Running java HelloQA.class or java HelloQA.java. The first is rejected, the second only works as a single-file shortcut on Java 11+. Always do javac HelloQA.java then java HelloQA (no extension) — it's the model every IDE and build tool uses.

🎯 Practice task

Build a real Java summary tool. 20-30 minutes.

  1. Create a folder java-for-qa and inside it a file RunReport.java.

  2. Declare a public class RunReport with a public static void main method (copy the shape from NightlySummary above).

  3. Inside main, declare four variables: String suite = "checkout-suite";, int passed = 47;, int failed = 3;, int duration = 215; (in seconds). Pick whatever values you like.

  4. Calculate int total = passed + failed;.

  5. Use System.out.println to print a multi-line report:

    Suite: checkout-suite
    Total: 50 | Passed: 47 | Failed: 3
    Duration: 215 seconds
    
  6. Compile with javac RunReport.java. Confirm a RunReport.class file appears.

  7. Run with java RunReport. Confirm the output matches your inputs.

  8. Stretch: add a line that prints the duration as minutes and seconds, e.g. Duration: 3 min 35 sec. Hint: integer division — int minutes = duration / 60; and int seconds = duration % 60; (we'll cover the maths properly in chapter 2).

You now have the shape every Java program is built on. The next lesson introduces variables and types so the values inside main stop being magic.

// tip to track lessons you complete and pick up where you left off across devices.