4 Unnamed Classes and Instance Main Methods
The addition of instance main methods and unnamed classes to the Java language enables students to write streamlined declarations for single-class programs and then seamlessly expand their programs later to use more advanced features as their skills grow.
Note:
This is a preview feature. A preview feature is a feature whose design, specification, and implementation are complete, but is not permanent. A preview feature may exist in a different form or not at all in future Java SE releases. To compile and run code that contains preview features, you must specify additional command-line options. See Preview Language and VM Features.
For background information about instance main methods and unnamed classes, see JEP 445.
The Java language enables development teams to create, develop, and maintain large and complex applications over many years. It is a multiparadigm language with rich features for data hiding, reuse, access control, namespace management, and modularity which allow components to be cleanly composed while being developed and maintained independently. With these features, components can expose well-defined interfaces for interaction with other components and also hide internal implementation details to permit the independent evolution of each. The object-oriented paradigm itself is designed for plugging together pieces that interact through well-defined protocols and also to abstract away implementation details. This composition of large components is called "programming in the large."
The Java language also offers many constructs useful for "programming in the small" in which everything is internal to a component. In recent years, it has enhanced its programming-in-the-large capabilities with modules and its programming-in-the-small capabilities with data-oriented programming.
The Java language is also intended to be a first programming language. When programmers first start out they do not write large programs, as part of a development team. They write small programs, alone. They have no need for encapsulation and namespaces which are useful to separately evolve components written by different people. When teaching programming, instructors start with the basic programming-in-the-small concepts of variables, control flow, and subroutines. At that stage there is no need for the programming-in-the-large concepts of classes, packages, and modules.
Hello, World!
program that is often
used as the first program for Java students:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
In this first program:
- The
class
declaration and the mandatorypublic
access modifier are programming-in-the-large constructs. They are useful when encapsulating a code unit with a well-defined interface to external components, but rather pointless in this little example. - The
String[] args
parameter also exists to interface the code with an external component, in this case the operating system's shell. It is mysterious and unhelpful here, especially since it is never used. - The
static
modifier is part of Java's class-and-object model. For the novice,static
is not just mysterious but harmful: To add more methods or fields thatmain
can call and use, the student must either declare them all asstatic
(thereby propagating an idiom which is neither common nor a good habit) or else confront the difference between static and instance members and learn how to instantiate an object.
The preview language features, instance main methods and unnamed classes,
reduce the complexity of writing simple programs such as Hello, World!
by enabling programmers to write programs without using access modifiers,
static
modifiers, or the String[]
parameter. The
introduction of programming-in-the-large constructs can be postponed by instructors
until they are needed.
Flexible Launch Protocol
New programmers want to write and run computer programs, but the current Java Language Specification focuses students on defining the core Java unit of the class and the basic compilation unit, namely a source file comprised of a package declaration, followed by import declarations and one or more class declarations.
The actions of choosing the class containing the main
method, assembling its dependencies in the form of a module path or a class path (or
both), loading the class, initializing it, and invoking the main
method
with its arguments constitute the launch protocol. In the JDK, the launch protocol is
implemented by the launcher as the java
executable.
main
methods, the new preview language features enhance the Java launch
protocol and provide greater flexibility in the declaration of a program's entry point
as follows:
- Allows the
main
method of a launched class to havepublic
,protected
, or default (such as package) access. - If a launched class does not contain a
static main
method with aString[]
parameter, but does contain astatic main
method without parameters, the launch protocol invokes that method. -
If a launched class does not contain a
static main
method, but has a non-private
zero-parameter constructor (such as,public
,protected
, or package access) and a non-private
instancemain
method, the launch protocol constructs an instance of the class. If the class has an instancemain
method with aString[]
parameter, the launch protocol invokes that method; otherwise, it invokes the instancemain
method with no parameters.
main
methods, we can simplify the Hello, World!
program presented in Unnamed Classes and Instance Main Methods
to:class HelloWorld {
void main() {
System.out.println("Hello, World!");
}
}
Selecting a main Method
This is a change of behavior when launching a class.
The launch protocol chooses to invoke the first of the following methods:
-
A
static void main(String[] args)
method of non-private access (such as,public
,protected
or package) declared in the launched class - A
static void main()
method of non-private access declared in the launched class -
A
void main(String[] args)
instance method of non-private access declared in the launched class or inherited from a superclass - A
void main()
instance method of non-private access declared in the launched class or inherited from a superclass
Note:
If the launched class declares an instancemain
method, that method will be invoked rather than an inherited
"traditional" public static void main(String[] args)
declared in a
superclass. Therefore, if the launched class inherits a "traditional"
main
method but another method (such as, an instance
main
) is selected, the JVM will issue a warning to the standard
error at runtime.
If the selected main
is an instance method and is a member
of an inner class, the program will fail to launch.
Unnamed Classes
In the Java language, every class resides in a package and every package resides in a module. These namespacing and encapsulation constructs apply to all code; however, small programs that do not need them can omit them.
A program that does not need class namespaces can omit the
package
statement, making its classes implicit members of the
unnamed package. Classes in the unnamed package cannot be referenced explicitly by
classes in named packages. A program that does not need to encapsulate its packages can
omit the module declaration, making its packages implicit members of the unnamed module.
Packages in the unnamed module cannot be referenced explicitly by packages in named
modules.
- Before they are comfortable with the basic building blocks of variables, control flow, and subroutines,
- Before they embark on learning object orientation, and
- When they are still writing simple, single-file programs.
When the Java compiler encounters a source file containing a method that is not enclosed in a class declaration, it implicitly considers such methods (as well as any unenclosed fields and any classes declared in the file) to be members of an unnamed top-level class.
An unnamed class is always a member of the unnamed package. It is also
final
and cannot implement any interface or extend any class other
than Object
. An unnamed class cannot be referenced by name, so
there can be no method references to its static methods. However, the
this
keyword can still be used, as well as method references to
instance methods.
No code can refer to an unnamed class by name, so instances of an
unnamed class cannot be constructed directly. Such a class is useful only as
a standalone program or as an entry point to a program. Therefore, an unnamed
class must have a main
method that can be launched as described
above. This requirement is enforced by the Java compiler.
An unnamed class resides in the unnamed package, and the unnamed
package resides in the unnamed module. While there can only be one unnamed package
(barring multiple class loaders) and only one unnamed module, there can be multiple
unnamed classes in the unnamed module. Every unnamed class contains a
main
method and represents a program. Multiple such classes in the
unnamed package represent multiple programs.
An unnamed class is almost exactly like an explicitly declared class.
Its members can have the same modifiers (such as private
and
static
) and the modifiers have the same defaults (such as
package
access and instance membership). The class can have static
initializers as well as instance initializers. One key difference is that while an
unnamed class has a default zero-parameter constructor, it can have no other
constructor.
Hello, World!
as:void main() {
System.out.println("Hello, World!");
}
String greeting() { return "Hello, World!"; }
void main() {
System.out.println(greeting());
}
String greeting = "Hello, World!";
void main() {
System.out.println(greeting);
}
HelloWorld.java
that contains an
unnamed class can be launched with the source-code launcher as
follows:$ java HelloWorld.java
The Java compiler compiles that file to the launchable class file
HelloWorld.class
. In this case, the compiler chooses
HelloWorld
for the class name as an implementation detail. However,
that name still cannot be used directly in Java source code.
At this time, the javadoc
tool will fail when asked to
generate API documentation for a Java file with an unnamed class because
unnamed classes do not define an API that is accessible from other classes.
This behavior may change in a future release.
The Class.isSynthetic
method returns true
for an unnamed class.
Growing a Program
A Hello, World!
program written as an unnamed class
is more focused on what the program actually does by omitting concepts and constructs it
does not need. Even so, all members are interpreted just as they are in an ordinary
class.
Concepts and constructs can be added to an unnamed class as as needed by the program. An unnamed class can easily be evolved later into an ordinary class, by wrapping its declaration (excluding import statements) inside an explicit class declaration.
Eliminating the main
method altogether might seem like a
natural next step, but it would work against the goal of gracefully evolving a student's
first Java program into a larger one as well as impose some non-obvious restrictions
(see see the section Alternatives in JEP 445). Dropping the
void
modifier would similarly create a distinct Java dialect.