Unnamed Classes and Instance Main: JEP 445/463 (Java 21+)

Traditional Java requires every program to live in a named class with a public static void main(String[] args) method: a significant hurdle for beginners and script authors. JEP 445 (preview in Java 21) and its follow-up JEP 463 (preview in Java 22) relax these constraints: you can write an instance main method, drop the String[] parameter, and, at the extreme, write a top-level method in a file with no class declaration at all. An "unnamed class".

Contents

Instance Main Method

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)
Java
// Classic — still valid
public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello from classic main");
    }
}
Java
// Instance main — no static, no public required
class Hello {
    void main() {
        System.out.println("Hello from instance main");
    }
}
Java
// 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.

Unnamed Classes

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.

Java
// File: Hello.java  (no class declaration needed!)

void main() {
    System.out.println("Hello, World!");
}
Java
// 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 + "!");
}
Java
// 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.

Compilation: --enable-preview

As of Java 21–23 these features are in preview and require the --enable-preview flag for both compilation and execution.

Shell
# 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
Shell
# 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.

Limitations vs Named Classes

  • 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.
Java
// 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
}

Use Cases: Scripts and Learning

Unnamed classes and instance main target two primary audiences: beginners learning Java for the first time, and script authors writing quick utilities.

Java
// 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));
}
Java
// 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));
}
Java
// 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.