Contents
- Instance Main Method
- Unnamed Classes
- Compilation — --enable-preview
- Limitations vs Named Classes
- Use Cases — Scripts and Learning
Before JEP 445/463 the only valid entry point was public static void main(String[] args). The new rules define a launch protocol that also accepts:
- void main(String[] args) — non-public, non-static (instance method), with args
- void main() — instance method, no args at all
- The classic public static void main(String[] args) still works (highest priority)
// Classic — still valid
public class Hello {
public static void main(String[] args) {
System.out.println("Hello from classic main");
}
}
// Instance main — no static, no public required
class Hello {
void main() {
System.out.println("Hello from instance main");
}
}
// Instance main with args — still no static needed
class Hello {
void main(String[] args) {
System.out.println("Args: " + java.util.Arrays.toString(args));
}
}
The launcher creates one instance of the class (using the no-arg constructor) and invokes the main method on it. If there are multiple qualifying main methods, priority is: static with args > static without args > instance with args > instance without args.
An unnamed class is a source file where top-level methods and fields are declared without an enclosing class declaration. The compiler implicitly wraps the contents in a class whose name is derived from the file name.
// File: Hello.java (no class declaration needed!)
void main() {
System.out.println("Hello, World!");
}
// File: Greeter.java
// Top-level fields and helper methods are allowed
String greeting = "Hello"; // instance field
void main() {
greet("World");
greet("Java");
}
void greet(String name) {
System.out.println(greeting + ", " + name + "!");
}
// File: FibScript.java
// Fibonacci — no class boilerplate
int fib(int n) {
return n <= 1 ? n : fib(n - 1) + fib(n - 2);
}
void main() {
for (int i = 0; i <= 10; i++) {
System.out.print(fib(i) + " ");
}
// 0 1 1 2 3 5 8 13 21 34 55
}
The implicit class has package-private access and cannot be referenced by name from other source files.
As of Java 21–23 these features are in preview and require the --enable-preview flag for both compilation and execution.
# Compile with preview (Java 21)
javac --enable-preview --release 21 Hello.java
# Run with preview
java --enable-preview Hello
# Or use the single-file source launcher (Java 11+)
java --enable-preview --source 21 Hello.java
# Java 22 — JEP 463 (second preview)
javac --enable-preview --release 22 FibScript.java
java --enable-preview FibScript
Preview features are fully specified and production-quality; they are held behind the flag to gather community feedback before being finalized. Check the release notes for the Java version you are using to confirm the status.
- No explicit class declaration — unnamed classes cannot be declared public, abstract, or final.
- Cannot be extended or referenced — other source files cannot import or reference an unnamed class by name.
- No package declaration — unnamed classes always belong to the unnamed package.
- No constructors with parameters — the launcher uses the no-arg constructor; you cannot define parameterized constructors.
- Cannot implement interfaces or extend classes explicitly — there is no syntax to add implements or extends when there is no class header.
- Static members are limited — you can declare static methods and static fields at the top level, but they belong to the implicit class.
// This is NOT possible in an unnamed class:
// public class Script { ... } — no class header
// class Script implements Runnable — no implements
// package com.example; — no package
// Static helper is fine:
static int square(int n) { return n * n; }
void main() {
System.out.println(square(7)); // 49
}
Unnamed classes and instance main target two primary audiences: beginners learning Java for the first time, and script authors writing quick utilities.
// File: SortDemo.java — a concise teaching example
import java.util.*;
var numbers = List.of(5, 2, 8, 1, 9, 3);
void main() {
var sorted = numbers.stream().sorted().toList();
System.out.println("Unsorted: " + numbers);
System.out.println("Sorted: " + sorted);
System.out.println("Max: " + Collections.max(numbers));
}
// File: HttpPing.java — quick script using HttpClient
import java.net.http.*;
import java.net.URI;
var client = HttpClient.newHttpClient();
void main() throws Exception {
var request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com"))
.GET()
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Status: " + response.statusCode());
System.out.println(response.body().substring(0, 100));
}
// File: WordCount.java — process files from command line
import java.nio.file.*;
void main(String[] args) throws Exception {
if (args.length == 0) {
System.err.println("Usage: java WordCount.java <file>");
return;
}
long count = Files.lines(Path.of(args[0]))
.flatMap(line -> java.util.Arrays.stream(line.split("\\s+")))
.filter(w -> !w.isBlank())
.count();
System.out.println("Words in " + args[0] + ": " + count);
}
Unnamed classes are not intended for production application code — use proper named classes, packages, and module structure there. Their strength is eliminating ceremony in exploratory and educational contexts.