Java 25 finalizes JEP 512, which makes small programs far less noisy: you can write a main as an instance method (no static required) and you can write compact source files — source files that implicitly declare a class for any top-level fields and methods. A light-weight java.lang.IO helper is available for beginner-friendly console I/O, and compact source files automatically gain access to java.base classes to reduce imports.
1. Intro — why this matters
For decades the first Java program looked like a barrier:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
That ceremony taught important concepts, but it also made the very first step into Java harder than necessary. JEP 512 gives a safe, compatible on-ramp: small programs can now be written with far less boilerplate while still being ordinary Java and fully upgradable into “real” Java classes as needed. This change is finalized in JDK 25.
2. What changed (short list)
- Compact source files: a source file that contains top-level fields and methods (not inside a class) is treated as implicitly declaring a
finaltop-level class whose members are those fields/methods. The class is unnamed and lives in the unnamed package/module. The compiler enforces that the file must have a launchablemain. - Instance
mainmethods:mainmay be declared as an instance method (for examplevoid main()orvoid main(String[] args)); when needed the launcher will instantiate the class and invoke the instancemain. This reduces the mental load ofpublic static void main(String[] args). java.lang.IOhelper: a small console I/O helper (methods likeIO.println(...)andIO.readln(...)) is provided injava.langfor convenience and is therefore available without imports. Its implementation usesSystem.out/System.in. Note: the static methods are not implicitly statically imported into compact source files — you call them asIO.println(...).- Automatic
java.baseimport in compact files: compact source files act as if the entirejava.basemodule were imported on demand — common classes likeList,Map,BigInteger, etc., are directly usable without an explicit import.
2. Compact Source Files
Before Java 25, every program must be inside a class, and the entry point was always:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
This was verbose for small demos or scripts.
👉 With compact source files, you can now write top-level methods and fields directly in a .java file. The compiler automatically wraps them inside an implicit final class behind the scenes.
Example 1: Hello World in a compact source file
// Hello.java
void main() {
IO.println("Hello, World!");
}
Run it directly:
java Hello.java
Output:
Hello, World!
➡️ No class, no static, no public. Just a simple entry point.
Example 2: Using fields and helper methods
You can declare fields and helper methods at the top level. They all become members of the implicit class.
// Greet.java
String greeting = "Welcome to Java 25!";
String shout(String text) {
return text.toUpperCase();
}
void main() {
IO.println(shout(greeting));
}
Run:
java Greet.java
Output:
WELCOME TO JAVA 25!
➡️ The compiler internally creates an unnamed class with greeting and shout as members.
3. Instance main Methods
Traditionally, Java only supported:
public static void main(String[] args)
With Java 25, you can now declare main as an instance method.
Example 3: Instance main without arguments
// Greeter.java
class Greeter {
void main() {
IO.println("Hello from an instance main!");
}
}
Run:
java Greeter.java
Output:
Hello from an instance main!
➡️ The launcher automatically creates an object of Greeter and invokes its main.
Example 4: Instance main with arguments
// Echo.java
class Echo {
void main(String[] args) {
for (var arg : args) {
IO.println("Arg: " + arg);
}
}
}
Run:
java Echo.java one two three
Output:
Arg: one
Arg: two
Arg: three
➡️ Both static and instance forms are supported:
void main()void main(String[] args)
4. IO Console Helper
To make small programs even simpler, Java 25 introduces java.lang.IO, a helper class for console input/output.
- Before Java 25:
System.out.println("Hello, Java!"); - Now:
IO.println("Hello, Java!");
Example 5: Using IO helper
void main() {
IO.println("Enter your name: ");
String name = IO.readln();
IO.println("Hello, " + name + "!");
}
Run and interact:
Enter your name:
Ashish
Hello, Ashish!
➡️ No need to remember System.out or set up a Scanner.
5. Automatic Imports
In compact source files, common Java APIs from java.base (like List, Map, BigInteger) are automatically available without import.
// Numbers.java
void main() {
var numbers = List.of(10, 20, 30);
IO.println("Numbers: " + numbers);
}
No import java.util.List; needed.
6. How Compact Source Evolves into a Class
Compact source files are not a new language, they’re just a shortcut.
You can always “grow” them into normal Java classes.
Compact form:
void main() {
IO.println("Quick start in Java 25!");
}
Expanded form:
class QuickStart {
void main() {
IO.println("Quick start in Java 25!");
}
}
This ensures seamless transition from beginner scripts to full OOP programs.
7. Important gotchas & notes
- Implicit class is unnamed and
final— the compiler generates a name you must not rely on in source code; you cannotnewthe implicitly-declared class from within the file. It’s meant as an entry-point, not a reusable API. - IO helper methods not implicitly imported as bare names — you must call
IO.println(...)(they live injava.langso no import is needed, but static implicit import into compact files was intentionally removed). - No statements outside methods — compact source files still require methods (you cannot write top-level statements that are executed as a script body; the design requires methods and fields so programs can grow).
- Launcher lookup rules — if a classic
public static void main(String[])exists it retains priority; instancemainpaths are fallbacks or alternatives. See the JEP/JVM spec for exact lookup semantics.
8. Compatibility & tooling
- JEP 512 was finalized for JDK 25; tooling (IDE support, linters) are already adding support (IntelliJ and other vendors published guidance shortly after the release). If your build tools or CI assume
public static void mainalways exists, you may want to update them to accept instance mains or use explicitjavac+javasteps.
9. Summary of Changes (JEP 512)
| Feature | Before Java 25 | Java 25+ (JEP 512) |
|---|---|---|
| Entry point declaration | public static void main(String[] args) | void main() or void main(String[] args) (static or instance) |
| Class requirement | Explicit public class ... | Implicit class (no explicit declaration) |
| Console I/O | System.out.println with imports | IO.println (available without import) |
| Import statements | Manual for core APIs | Auto-import for java.base in compact files |
👉 Read more:
- Official JEP 512 Documentation
- official announcement from Oracle about JDK 25 (JEP list and status). Oracle Releases Java 25
- Oracle docs on compact source files & instance main methods (includes run examples). Oracle Docs
