Java Compact Source Files: No Class, No Static Main
Java has traditionally required a class and a static main method even for the smallest programs. Java 25 changes this with compact source files and instance main methods, providing a simpler way to write and run small Java programs while retaining Java’s class-based programming model.
1. Introduction
Java 25 makes it possible to write small Java programs with much less boilerplate. With compact source files, you do not have to explicitly declare a class. Java also supports instance main methods, so main does not have to be static. This is especially useful for learning Java, writing examples, experimenting with APIs, and creating small programs.
1.1 The Old Way
A traditional Java program commonly starts like this:
public class Hello {
public static void main(String[] args) {
System.out.println("Hello, Java!");
}
}
Even for one line of application logic, we need a class declaration, public static void main(String[] args), and the call to System.out.println().
1.2 The New Way: A Compact Source File
With Java 25, the same small program can be written as:
void main() {
IO.println("Hello, Java!");
}
There is no explicit class declaration, and main() is not static. Java provides the surrounding class automatically.
1.3 Before and After
| Traditional Java | Compact Source File |
|---|---|
| Explicit class declaration | No explicit class declaration |
public static void main(String[] args) | void main() |
System.out.println() | IO.println() can be used |
| More setup for small programs | Less boilerplate |
2. Compact Source File Example: IO, Input, Fields, Methods, and Imports
The following is a complete Java 25 compact source file. You can copy the entire example into a file such as Greeting.java and run it using JDK 25.
String appName = "Greeting App";
String createGreeting(String name) {
return "Hello, " + name + "!";
}
void main() {
IO.println(appName);
IO.println("----------------");
IO.print("This program is running with ");
IO.println("Java 25.");
String name = IO.readln("Enter your name: ");
IO.println(createGreeting(name));
List<String> topics = List.of("Compact Source Files", "Instance main", "java.lang.IO");
IO.println("Topics covered:");
for (String topic : topics) {
IO.println("- " + topic);
}
}
2.1 Code Explanation
The example demonstrates a complete Java 25 compact source file without an explicit class declaration or a traditional public static void main(String[] args) method. The appName field stores the application name, while List is used without an explicit import because compact source files automatically import public top-level classes and interfaces exported by the java.base module. The createGreeting() method accepts a name and returns a personalized greeting. The program starts with the instance void main() method, where IO.print() and IO.println() are used to display text on the console and IO.readln() reads the user’s name. The entered name is passed to createGreeting() and the returned greeting is printed. Next, List.of() creates an immutable list containing the topics demonstrated by the program, and an enhanced for loop iterates through the list and prints each topic. Although no class is explicitly written, the field and methods in this compact source file become members of an implicitly declared class created as part of Java’s compact source file model.
2.2 Code Output
Make sure JDK 25 is installed and verify the installed version using java --version. Save the program as Greeting.java and run the source file directly using java Greeting.java. Since compact source files are a final feature in JDK 25, the --enable-preview option is not required.
Greeting App ---------------- This program is running with Java 25. Enter your name: Rahul Hello, Rahul! Topics covered: - Compact Source Files - Instance main - java.lang.IO
The output begins by displaying the application name, Greeting App, followed by a separator and a message confirming that the program is running with Java 25. The program then prompts the user to enter a name using IO.readln(); in this example, the user enters Rahul. The entered value is passed to the createGreeting() method, producing and displaying Hello, Rahul!. Finally, the program prints the Topics covered: heading and uses a for loop to display each item from the topics list on a separate line.
2.3 Important Rules for Compact Source Files
- Implicit class: Although you do not explicitly declare a class, Java implicitly declares a top-level class containing the fields and methods in the compact source file. This implicitly declared class belongs to the unnamed package and has an implicitly declared default constructor.
- No package or explicit class declaration: A compact source file does not need a
packagedeclaration or an explicit class declaration. For example, a file namedGreeting.javacan directly contain fields, methods, andvoid main()without declaringclass Greeting. The name of the implicitly declared class is determined by the host system and, in a typical file-based Java implementation, is based on the source file name. - Implicit imports: Compact source files make commonly used Java APIs easier to access.
IObelongs tojava.lang, soIO.print(),IO.println(), andIO.readln()can be used without importingjava.lang.IO. Compact source files also receive additional implicit imports for public top-level classes and interfaces exported by thejava.basemodule. Normal explicitimportdeclarations can still be used when needed. - JDK requirement: Compact source files and instance
mainmethods are final features in JDK 25. Earlier JDK releases provided predecessor versions as preview features, but JDK 25 finalizes them through JEP 512. Therefore,--enable-previewis not required when using the finalized feature in JDK 25.
2.4 When Should You Use Compact Source Files?
Compact source files are best suited to small programs, tutorials, coding exercises, demonstrations, prototypes, and simple command-line utilities. For larger applications that require multiple classes, named packages, modules, reusable APIs, and a well-defined project structure, the traditional Java class-based source-file format remains more appropriate.
3. Instance main() Methods in a Normal Class
The new form of main() is not limited to compact source files. A normal explicitly declared class can also use an instance main method. Consider the following Application.java:
class Application {
Application() {
System.out.println("Creating Application");
}
void main() {
System.out.println("main() without arguments");
}
void main(String[] args) {
System.out.println("main(String[] args)");
System.out.println("Arguments: " + args.length);
}
}
3.1 Code Explanation
The Application class demonstrates Java 25 instance main methods and how Java selects a program entry point. The no-argument Application() constructor prints Creating Application when Java creates an instance of the class. The class then declares two overloaded instance main methods: main(), which takes no arguments, and main(String[] args), which accepts command-line arguments. Because both are candidate main methods, Java selects main(String[] args) in preference to main(). Since the selected method is not static, Java first creates an Application object using its no-argument constructor and then invokes main(String[] args) on that object. The method prints its name and displays the number of command-line arguments using args.length.
3.2 Code Output
Creating Application main(String[] args) Arguments: 0
The output first displays Creating Application because Java creates an instance of the Application class using its no-argument constructor before invoking the instance main method. Since the class contains both main() and main(String[] args) candidate methods, Java selects main(String[] args), which prints main(String[] args). Finally, Arguments: 0 is displayed because the program was executed without any command-line arguments, so the length of the args array is zero.
4. Conclusion
Java 25’s compact source files and instance main methods significantly reduce the boilerplate required to write small Java programs. A program can now start with a simple void main() method without explicitly declaring a class or making main static. The java.lang.IO class further simplifies console applications by providing convenient methods such as IO.print(), IO.println(), and IO.readln(). Compact source files still follow Java’s class-based model: Java implicitly declares the surrounding class, while fields and methods written in the source file become members of that class. Java 25 also allows instance main methods in normal explicitly declared classes, giving developers more flexibility in defining an application’s entry point. These features are particularly useful for learning Java, coding exercises, demonstrations, prototypes, and small command-line programs. They are not intended to replace traditional classes, packages, and application structure for larger projects. Instead, Java 25 provides a simpler starting point when the additional structure is unnecessary, while allowing developers to move naturally to conventional Java application design as programs grow.

