3. Hello world explained

Hello world lessons

Let's summarize what we learned from the last section's exercises:

Also, Java programs always start execution from the main method.

Anatomy of an error message

In the last section's exercises, you got acquainted with some error messages. Now, let's break down their structure. It's important to be comfortable reading error messages because they're crucial for debugging.

In general, an error message looks like this:

Filename.java:line number: Possible cause
    Print out of the error messages or the line Java thinks is wrong

Let's look at a simple error output.

$ javac Test.java
Test.java:3: ';' expected
1 error

The first line tells us what file the error is in, followed by the line number. So the error is in Test.java at line 3. Below that, Java describes what it thinks the error is, which can often be completely wrong. In this case, Java is correct; I was missing a semicolon after the print statement.

Let's look at another one:

Test.java:3: unclosed string literal
Test.java:3: ';' expected
Test.java:5: reached end of file while parsing
3 errors

Errors can sometimes multiply. I forgot the closing quotation mark to "hello, which caused Java to miss the semicolon at the end of the line and the closing bracket for main. Java is seeing three errors when there is only one.

The lesson here is to always start with the first error. Once I added the closing " to "hello, all of the other errors went away, too.

The above errors were caught while compiling, i.e. after I ran the javac command. But once you fix any compiler errors, there's still no guarantee your program will actually run - the compiler can only catch very basic errors.

For example, you saw in the previous exercises that if we forget the static keyword in main's declaration, our program will compile correctly but fail at runtime:

$ javac Test.java // compiles just file
$ java Test
Exception in thread "main" java.lang.NoSuchMethodError: main // oops!

And as also saw previously, if we name our class something different than the filename, we get this runtime monstrosity:

$ javac Test.java // compiles just fine
$ java Test
Exception in thread "main" java.lang.NoClassDefFoundError: Test (wrong name: test)
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClassCond(ClassLoader.java:637)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:621)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
    at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)

All of the error lines after the first are simply tracing the error through the JVM. We can safely ignore those and only look at the first line, which tells us that the error was a NoClassDefFoundError and that Java thinks our class was given the wrong name. In this case, my class was named test but the filename was Test.java.

In sum, error messages can sometimes be very confusing. But if you slow down, take a deep breath, and start from the top, usually you can make sense of what's going on. The more comfortable you are with Java's vocabulary of errors and exceptions, the better you'll be at debugging.

Exceptions vs errors

Exceptions are problems that your program can probably handle without crashing. For example, if we try to open a file that doesn't exist, we'll get a FileNotFoundException. Instead of crashing, our program could catch this exception, print out something like "File not found", and then exit gracefully.

Errors are serious problems that your program probably isn't going to recover from. For example, if you get an OutOfMemoryError, your program is just going to crash and there's really nothing you can do about it.

In this course, I'll use the terms "error" and "exception" interchangably.


A majority of programming time is usually spent debugging, so the faster you can debug, the faster you'll be able to program. The first two exercises will give you more practice with error messages and the final two with printing.

Even if you see what the bugs are right away, don't fix them without compiling. Fix one error at a time and compile after every change so you can actually get used to the error outputs.

  1. Go through this very broken program and fix the bugs. Remember to name your file exactly the same as the class. (Hint: it may be helpful to reformat the code with correct indentation).

            / This code totally won't work.
    System.out.println("I'm a print statement."); class PrettyTerrible {  
    System.out.println('Woo hoo, I'm printing stuff!'); public static main(Stirng[] args) {
        print("Hello world!");
    System.out.println("Hey, I want to say hello too!")System.out.println("Me too!); }
  2. Fix the bugs in this program, too:

    // This is slightly less broken, but still bad
    class LessBad() {
        public statc void main string args {
        System.out.print("Hello ");
        System.out.println(" world!") }
    } }
  3. Print out the numbers 1 through 5 on separate lines, like this:


    Can you do this using only one print statement? (Hint: remember \n?) Google how to do this if you get stuck, but don't worry if you can't figure it out.

  4. Print out the numbers 1 through 5 on the same line, like this:

    1 2 3 4 5

    Can you do this using 5 different print statements? (Remember to use Google).