Skip to content
Chapter 04 · Core Java

Why Only One Public Class Per Java File ​

One .java file can hold many classes, but at most one of them can be public. This chapter explains why, starting from how the JVM runs your program.

How the JVM Starts Your Program ​

The JVM starts a program by calling main through the class name, for example Employee.main(args). That is why main is static: no object is needed.

The JVM does not read .java files. javac first turns every class in your file, public or not, into its own .class file, and the JVM loads those. The class that contains main does not have to be public:

java
// File name: Whatever.java
class Employee {                       // package-private
    public static void main(String[] args) {
        System.out.println("program started");
    }
}
javac Whatever.java      // produces Employee.class
java Employee            // prints: program started

So the one-public-class rule is not about starting the program. It is a compiler rule about finding source code.

The Rule: A Public Class Name Must Match the File Name ​

If a file contains a public top-level class, the name of that class must be exactly the same as the name of the file.

If your file is called Employee.java, the only public class allowed in that file must be named Employee. You cannot write public class Manager inside a file called Employee.java. The compiler will refuse to compile it.

java
// File name: Employee.java

public class Manager {  // COMPILE ERROR
    // The compiler says: class Manager is public, should be declared in a file named Manager.java
}

You will get an error message that looks exactly like this:

error: class Manager is public, should be declared in a file named Manager.java

The compiler itself tells you the rule. The public class name must match the file name.

Why Does This File Name Rule Exist? ​

The reason comes from the Java Language Specification (JLS §7.6).

A public class can be used by code in any other package. Imagine you are compiling Payroll.java, and it refers to com.acme.hr.Employee. The compiler needs to find Employee. If it has not been compiled yet, the compiler must find its source code. Without a naming rule, it would have to open and parse every .java file in the com/acme/hr directory to discover which one declares Employee. In a large codebase, that is slow and fragile.

With the rule, the lookup is trivial: com.acme.hr.Employee must live in com/acme/hr/Employee.java. The JLS states the purpose directly: the restriction "makes it easy for a Java compiler to find a named class or interface within a package."

How One Public Class Per File Follows ​

The limit follows directly from the rule. A public class must match the file name, and a file has only one name. So a file can contain at most one public top-level class. The JLS even spells this out: the restriction "implies that there must be at most one such class or interface per compilation unit."

Imagine Java allowed two public classes in one file. Say the file is called Employee.java and it contains public class Employee and public class Manager. The compiler compiling some other file that refers to Manager would look for Manager.java, not find it, and fail. The rule only works if there is at most one public class per file.

Walking Through a Full Example ​

Let us look at a file with multiple classes to see exactly how this works in practice.

java
// File: Employee.java

public class Employee {
    // This is the public class. Its name matches the file name. This is correct.
    
    public static void main(String[] args) {
        System.out.println("Program starts from Employee");
        
        // We can use the other classes in this file
        Helper helper = new Helper();
        helper.doWork();
        
        Manager manager = new Manager();
        manager.manage();
    }
}

// This class has no access modifier. That makes it package-private.
// It is completely valid to have this here.
class Helper {
    void doWork() {
        System.out.println("Helper is doing work");
    }
}

// Another package-private class. Also completely valid.
class Manager {
    void manage() {
        System.out.println("Manager is managing");
    }
}

// public class Director { }  // This would be a COMPILE ERROR.
// You cannot have a second public class in Employee.java.

This file compiles and runs perfectly. You have one public class named Employee that matches the file name. You also have two additional classes, Helper and Manager, but neither of them is public. They are package private. The rule does not restrict package private classes at all. You can have as many of them as you want in a single file.

What Package Private Actually Means ​

When you write a class without any access modifier, like this:

java
class Helper {
    void doWork() { }
}

That class is package private. It is visible to all other classes within the same package, but it is invisible to code outside the package. This is a completely valid and useful visibility level. It is perfect for helper classes that support the public class but are not meant to be used directly by anyone outside the package.

The compiler's file name lookup problem mainly concerns public classes, because they can be referenced from any package. Package private classes can only be used inside their own package, so they can live alongside the public class in the same file.

Check yourself ​

  1. Why can a .java file contain at most one public top-level class?
  2. Does the JVM use the .java file name to find your class at runtime?
  3. Must the class containing main be public?
  4. Can a file contain zero public classes? How many package-private classes can it contain?
  5. What error do you get for public class Manager inside Employee.java, and when?
Answers
  1. A public class must live in a file with its own name (JLS §7.6), so the compiler can find its source instantly. One file has one name, so it can hold at most one public top-level class.
  2. No. The JVM only loads .class files, one per class. The naming rule is for the compiler.
  3. No. main in a package-private class runs fine with java ClassName. Using a public class is only convention.
  4. Yes, zero public classes is fine, and the file name can be anything. There is no limit on package-private classes.
  5. A compile-time error: class Manager is public, should be declared in a file named Manager.java.