The name main
is not reserved by the Java Programming Language. It’s an ordinary identifier and thus, the same rules as with all other identifiers apply. You can have multiple methods named main
as long as they have different parameter types. That’s called method overloading.
The special meaning of a certain main
method is defined by the Launcher which initializes your application and this startup procedure defines the rules. Note that there might be different, implementation specific, ways to launch an application, e.g. Applet
s don’t have a main
method and JavaFX provides its own Launcher that works without a main
method. The same applies to several server-side Java technologies. This doesn’t prevent you from declaring main
methods when using such technologies, but they don’t have a special meaning.
So the well-known java
launcher, using command line arguments, searches for a special method named main
having the raw signature public static void main(java.lang.String[])
in the specified main class. Note that there were earlier Java versions whose launcher didn’t care about the presence or absence of the public
modifier. All that matters to the launcher is, whether it finds such a main
method. It doesn’t care about other methods of the same name and different signature. It also doesn’t care whether other classes have an appropriate main
method. All it does, is searching for an appropriate method in the specified class.
Since only the raw (bytecode level) signature of the method matters, it is irrelevant, which source code form it has, as long as it got compiled to a method with the appropriate signature. Thus, the following declarations will lead to a main
method, appropriate for launching a Java application:
public static void main(String[] arg) {}
public static void main(String arg[]) {} // source code variantion don’t matter
public static void main(String... arg) {} // varargs are compiled to an array type
public static final void main(String[] arg) {} // final is irrelevant
public interface Example {
static void main(String[] arg) {} // public is implied (Java 8)
}
public static <T extends String> void main(T[] arg) {} // raw parameter type is String[]
Note that with the last variant, some IDEs failed to launch the application (despite it works from command line), showing that the actual behavior dependents on the implementation of the launcher.
In contrast, the following doesn’t work:
class String{}
public static void main(String[] arg) // the parameter type is not java.lang.String[]
demonstrating, that not the source code form but the compiled raw signature matters. When trying to run the last example, the launcher will complain that it doesn’t find the required method public static void main(String[])
, not telling you that there is a different, non-matching main
method. As said, it doesn’t care about other methods of that name.