Introducing Unnamed Classes and Simplified Main Methods in Java
Java has long been known for its verbosity, especially when it comes to writing simple scripts or small programs. With Java 21’s introduction of simplified main methods, developers can now write more concise and readable entry points for their applications. The feature is primarily to teach Java by just making it easier to start.
The Traditional Main Method
Traditionally, Java required a verbose main method declaration in an enclosing class:
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}
The New Simplified Approach
Now, Java allows a more streamlined syntax that reduces boilerplate code:
void main() {
    System.out.println("Hello, World!");
}
No surrounding public class, no public static and no String[] args - much easier to parse for a new
starter to the language.
This can be stripped back further from Java 24 using the new static methods from the IO class:
void main() {
    IO.println("Hello, World!");
}
Scripting Superpowers
The new main method syntax comes with some exciting features that make Java more script-friendly:
- Direct Execution
You can now run Java files directly without explicit compilation as 
java Helloworld.java - Shell Script Compatibility
An ingenious trick allows you to make Java files executable - paste this comment into the top of the
java source file 
///usr/bin/env java "$0" "$@" ; exit $?. When added to the top of your Java file, this line:- Makes the file directly executable
 - Remains valid Java code
 - Works across most shell environments
 
///usr/bin/env java "$0" "$@" ; exit $? void main() { IO.println("Hello, World!"); }and then:
$ chmod +x Helloworld.java $ ./Helloworld.java 
Practical Benefits
- Easier for Beginners
    
- Reduced boilerplate
 - More approachable syntax
 - Lower entry barrier for new developers
 - Scripting Workflow Improvements
 
 - Direct file execution
    
- No need for separate compilation step
 - Seamless integration with shell scripts
 
 
Third Party Libraries
How do you include these? Just standard Java classpath. Rather than create a fairly heavyweight maven or gradle project for a simple script lets just add the dependencies into the current directory and using the 3rd party jpm package manager. Install it and then install jfiglet to make a banner.
///usr/bin/env java "$0" "$@" ; exit $?
import com.github.lalyos.jfiglet.FigletFont;
void main(String[] args) {
  try {
    if (args.length == 0) {
      print(FigletFont.convertOneLine("Hello world!"));
    } else {
      print(FigletFont.convertOneLine(args[0]));
    }
  } catch (java.lang.Exception e) {
    System.err.println(e);
  }
}
$ java --enable-preview -cp deps/* Helloworld.java 
  _   _      _ _                            _     _ _ 
 | | | | ___| | | ___   __      _____  _ __| | __| | |
 | |_| |/ _ \ | |/ _ \  \ \ /\ / / _ \| '__| |/ _` | |
 |  _  |  __/ | | (_) |  \ V  V / (_) | |  | | (_| |_|
 |_| |_|\___|_|_|\___/    \_/\_/ \___/|_|  |_|\__,_(_)
                                                      
You’ll notice in this version how the flexible main signature can accept cli arguments as well so we can use it
to specify the text to output.
 $ java --enable-preview -cp deps/* Helloworld.java "It is ten o'clock"
  ___ _     _       _                     _      _            _    
 |_ _| |_  (_)___  | |_ ___ _ __     ___ ( ) ___| | ___   ___| | __
  | || __| | / __| | __/ _ \ '_ \   / _ \|/ / __| |/ _ \ / __| |/ /
  | || |_  | \__ \ | ||  __/ | | | | (_) | | (__| | (_) | (__|   < 
 |___|\__| |_|___/  \__\___|_| |_|  \___/   \___|_|\___/ \___|_|\_\
 
We need the enable-preview switch until it is officially released in Java 25.
Performance
It is not super quick as there is still a hidden compile step going on under the covers but as a way to write scripts it works very well.
$ time java --enable-preview -cp deps/* Helloworld.java 
  _   _      _ _                            _     _ _ 
 | | | | ___| | | ___   __      _____  _ __| | __| | |
 | |_| |/ _ \ | |/ _ \  \ \ /\ / / _ \| '__| |/ _` | |
 |  _  |  __/ | | (_) |  \ V  V / (_) | |  | | (_| |_|
 |_| |_|\___|_|_|\___/    \_/\_/ \___/|_|  |_|\__,_(_)
                                                      
real    0m0.385s
user    0m0.811s
sys     0m0.084s
Comparing the two methods to make this run we can see that normal pre-compiling with javac and then
executing with java is faster.
$ javac --enable-preview --release 24 -cp deps/* Helloworld.java 
$ time java --enable-preview -cp deps/*:. Helloworld
  _   _      _ _                            _     _ _ 
 | | | | ___| | | ___   __      _____  _ __| | __| | |
 | |_| |/ _ \ | |/ _ \  \ \ /\ / / _ \| '__| |/ _` | |
 |  _  |  __/ | | (_) |  \ V  V / (_) | |  | | (_| |_|
 |_| |_|\___|_|_|\___/    \_/\_/ \___/|_|  |_|\__,_(_)
                                                      
real    0m0.083s
user    0m0.105s
sys     0m0.038s
Graal Native Image
As an aside how about seeing how fast we can make it run as a native image. Do the following:
- Compile the class as before 
javac --enable-preview --release 24 -cp deps/* Helloworld.java - Run the Graal native image tool 
native-image --enable-preview -H:IncludeResources=".*/*.flf" -cp deps/*:. HelloworldIn addition to passing the dependencies as classpath arguments plus the classfile we also need to tell the native compiler that we want to include resources in this case files in the dependency jar needed at runtime. Miss these and the input stream used to read them fails. 
$ time ./helloworld 
  _   _      _ _                            _     _ _ 
 | | | | ___| | | ___   __      _____  _ __| | __| | |
 | |_| |/ _ \ | |/ _ \  \ \ /\ / / _ \| '__| |/ _` | |
 |  _  |  __/ | | (_) |  \ V  V / (_) | |  | | (_| |_|
 |_| |_|\___|_|_|\___/    \_/\_/ \___/|_|  |_|\__,_(_)
                                                      
real    0m0.017s
user    0m0.006s
sys     0m0.011s
Very quick but we obviously trade the scripting benefits.