Skip to main content

Section 8.1 Compilation, Main Method, Packages

A Java program consists of one or more files with the file ending .java. Every .java file declares a class. This class must have the same name as the file. For example, a file X.java needs to contain a declaration for a class X:

public class X {
}

The Java compiler javac translates a file X.java into the class file X.class. This file corresponds to the .o object files that we know from C. It contains information about the class and the so-called Java bytecode for the functions of the class. Java bytecode is an abstract machine language that is executed by the Java runtime environment. Java programs are started from the command line with a call to the Java runtime environment: java X. For this to work, there needs to be a class file X.class that contains a function with the name main. Our first Java program is therefore:

public class X {
    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}

We compile it to a class file with

$ javac X.java

which we execute with

$ java X

Java recognizes a function main only as the program's starting point if it has the return type void and a parameter of the array type String[]. The main function further needs to be decorated with the keywords public and static. The parameter args of main is a sequence of character strings. It is used to pass the provided command line parameters to the program. For instance, the following program prints its command line parameters, each in a separate line:

public class ArgPrinter {
    public static void main(String[] args) {
        for (String s : args)
            System.out.println(s);
    }
}

It operates as follows:

$ java ArgPrinter these are five arguments now
these
are
five
arguments
now

In contrast to C, the name of the executable is not included in the argument sequence.

Subsection 8.1.1 Multiple Classes

Realistic Java programs consist of more than one class (and therefore also multiple files). Each class defines its own visibility scope or namespace. The identifiers that are declared in a class (like, for instance, main above), are by default only visible inside the class. By qualification, we can still use them in other scopes:

// Y.java
public class Y {
    static void sayHello() {
        System.out.println("Hello");
    }
}

// X.java
public class X {
    public static void main(String[] args) {
        Y.sayHello();
    }
}

In this example, the identifier Y.sayHello is qualified with the name of the class where it is declared. Java provides ways to restrict the use of qualification to manage the accessibility of identifiers. Section 8.5 provides more details on this topic.

Subsection 8.1.2 Packages

The many classes of a typical Java project can be structured in packages. We express that the class X is part of the package p with a package statement as follows:

package p;

public class X {
}

The package structure is implicitly linked to the directory structure of the .java files. In the above example, the Java compiler will expect that the file X.java is in the subdirectory p. Classes from other packages can be accessed either via qualification with the package name or by importing the package. For instance, consider the class Y in the package p1:

// p1/Y.java
package p1;

public class Y {
    static void sayHello() {
        System.out.println("Hello");
    }
}

If we want to refer to Y from within a class X in the package p2, we can do so as follows, using qualification:

// p2/X.java
package p2;
public class X {
    public static void main(String[] args) {
        p1.Y.sayHello();
    }
}

Or we can use a package import:

// p2/X.java
package p2;

import p1.Y;

public class X {
    public static void main(String[] args) {
        Y.sayHello();
    }
}