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. Applets 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.
main(String[] args)the others one are just there to call from other classes i'm assuming. or when class loading and stuffString[]version (of which there are 3 compatible versions of syntax)