Introduction to Java Main Method
In the realm of Java, the main method is the entry point of any standard Java application. Think of it as the grand gateway to the world of your Java program. Whether you've written a complex software or a simple "Hello, World!" program, the Java Virtual Machine (JVM) looks for this method to kickstart the execution of your application.
While most programming languages have some concept of a starting point, the main method in Java holds significance not just as a start but as a convention. Without it, your standalone Java application simply cannot begin its execution. This convention is so entrenched that even the most advanced Integrated Development Environments (IDEs) automatically scaffold it when you create a new Java project.
Syntax of the Java Main Method
The signature of the main method is unmistakable and unique:
public static void main(String[] args)
Let's briefly deconstruct it:
- public: This access modifier allows the main method to be accessible everywhere, ensuring the JVM can call it without any access restrictions.
- static: Being a static method means you don't need an instance of the class to call the main method. This is vital, as your application hasn't begun and no objects have been created when the JVM starts the execution.
- void: The main method doesn't return anything. It's the start, not a process that gives back a result.
- main: It's the name of the method that the JVM looks for.
- String[] args: This parameter allows the method to accept an array of string values – these are command-line arguments that can be passed when starting your application.
Why public static void main(String[] args)
?
When you start learning Java, one of the first lines of code you encounter is public static void main(String[] args)
. This is the entry point for every Java application—a gateway through which the Java Virtual Machine (JVM) starts running your code. But why exactly is this the convention? Let's dissect each part of this signature:
Role of public
:
The public is a Java keyword that declares a member's access as public. Public members are visible to all other classes. This means that any other class can access a public field or method. Further, other classes can modify public fields unless the field is declared as final. The main method in java is public so that it can be accessible everywhere and to every object which may desire to use it for launching the application.
Notice that if we will not make the Java main method public, then there will be no compilation error. But we will get runtime error because matching the main method is not present. Remember that the whole syntax should match to execute the java main method. For example, see the example below:
Notice that it says the main.java is not executable, that is because our main method is not public.
Role of static
:
In the Java programming language, the keyword static indicates that the particular member belongs to a type itself, rather than to an instance of that type. This means that only one instance of that static member is created which is shared across all instances of the class. In simple words, static methods are the method that invokes without creating the objects, so we do not need any object to call the main method. If we will not make the main method static we will get the following error. See the example below:
// class
public class Main {
// main method withou static keyword
public void main(String args[]){
System.out.println("golinuxcloud!!");
}
}
Output:
Notice that it says the Java main method is not found and gave us the proper syntax of the main method.
Role of void
:
The void keyword specifies that a method should not have a return value. In java, every method should have a return type otherwise we will get an error. The main method's type is void which means that it is not returning anything. If we create the main method without any return type (void) we will get the following error.
Purpose of String[] args
:
The java main method can also accept some data from the user. It accepts a group of strings, which is called a string array. It is used to hold the command line arguments in the form of string values. The agrs[]
is actually an array name, and it is of String type. It means that it can store a group of strings. Remember, this array can also store a group of numbers but in the form of a string only. Values passed to the main method are called arguments. These arguments are stored into args[]
array, so the name args[]
is generally used for it.
Now we are familiar with the terms used in the java main method, we are good to go and create a main method and run it. See the example below which prints out a message.
// class
public class Main {
// main method
public static void main(String args[]){
// message
System.out.println("welcome to golinuxcloud java tutorials!");
}
}
Output:
welcome to golinuxcloud java tutorials!
Passing arguments to Java main method
Passing arguments to the Java main
method is a common way to provide input parameters to a Java application at the time of its execution. These arguments can be used to customize the behavior of the program, specify configuration settings, or provide input data.
Running Java file from using commands
To run the java file from the terminal, first, open the terminal and then using cd
command and folder name, go the directory where the Java file is saved. Once you are in the same directory then use the following commands to run the java file. See the syntax below:
java className.java
For example, let us say we have the following java program.
// class
public class Main {
// main method withou static keyword
public static void main(String args[]){
// message
System.out.println("Welcome to go linux cloud");
}
}
Now we will use the command line to run this program. See the result below:
Notice that the java program was run successfully.
Passing arguments to java main method through command line
We already learned how to run a java program using the terminal and commands. Now, we are good to pass arguments to the java main method using the terminal. The following is the simple syntax of passing arguments to the main method using the command line.
java className.java arguments
Now let us say we have the following java program which prints out the arguments of the main method. See the example java program below:
// class
public class Main {
// main method withou static keyword
public static void main(String args[]){
// printing arguments of main method
System.out.println(args[0]);
System.out.println(args[1]);
}
}
Now let us run the program using the command line. See the result below:
Notice that we successfully passed a string argument to the java main method and prints out using indexing.
Converting Arguments
In Java, when arguments are passed to the main
method, they are received as an array of strings (String[] args
). Depending on your program's needs, you might have to convert these strings into other data types or use them in specific ways.
To Integer:Â To convert a string argument to an integer, you can use the parseInt
method from the Integer
class.
int number = Integer.parseInt(args[0]);
To Double: For decimal numbers, use the parseDouble
method from the Double
class.
double value = Double.parseDouble(args[1]);
To Boolean: The Boolean
class provides a method parseBoolean
which will return true
for a string argument "true" (case insensitive), and false
for anything else.
boolean flag = Boolean.parseBoolean(args[2]);
Checking for Specific String Values: You can compare string arguments with specific values using the equals
method.
if(args[3].equals("start")) {
// do something
}
Using Arguments
As File Paths: Arguments can be used as paths to files or directories for reading/writing operations.
File file = new File(args[4]);
As Configuration Flags: You can use arguments to change the behavior or configuration of your program.
if(args[5].equals("--verbose")) {
// enable verbose mode
}
As Inputs for Operations: Arguments can directly be inputs for specific operations in your program.
String username = args[6];
String password = args[7];
login(username, password);
Overloading the Java Main Method
In Java, method overloading is the practice of defining multiple methods in the same class with the same name but different parameters. Similarly, you can overload the main
method. However, there are a few key points to understand:
1. JVM's Entry Point: The Java Virtual Machine (JVM) recognizes only one signature of the main
method as the entry point of a Java program:
public static void main(String[] args)
This is the method that gets executed when you run your Java class.
2. Overloading the Main Method: Even though JVM recognizes only the above signature as the entry point, nothing stops you from overloading the main
method. Here are a couple of examples:
public static void main(String arg1, String arg2) {
// This is an overloaded main method
}
public static void main(int arg1) {
// Another overloaded main method
}
3. Invocation of Overloaded Methods: The overloaded main
methods don't get executed automatically by the JVM. If you want them to run, you must call them explicitly from the standard main(String[] args)
method or from some other method in your program:
public static void main(String[] args) {
main("arg1", "arg2"); // Calling the overloaded main method
main(123); // Calling another overloaded main method
}
4. Error Scenarios: Remember, if the JVM doesn't find the standard main(String[] args)
signature in your class and you try to run it, you will get an error like:
Error: Main method not found in class MyClass, please define the main method as:
public static void main(String[] args)
Main Method without String[] args
The main
method with the signature public static void main(String[] args)
is conventional in Java because it's the entry point that the Java Virtual Machine (JVM) looks for when running a Java program. The String[] args
parameter is designed to capture command-line arguments that might be passed to the program.
However, you can have a main
method without String[] args
, but there are some things to note:
If you have a main
method like this:
public static void main()
The JVM won't recognize it as the entry point for your application. If you attempt to run the class directly, you'll get an error.
Such a main
method can be invoked manually from another main
method with the correct signature or any other static method in your program:
public class Test {
public static void main() {
System.out.println("Main without args");
}
public static void main(String[] args) {
main();
}
}
So, while it's technically possible to have a main
method without the String[] args
parameter, it's non-standard and won't serve as the entry point for your application.
Using varargs with Main Method
In Java, varargs (variable-length argument lists) is a feature that allows a method to accept zero or more arguments of a specific type. The syntax uses ellipses (...
) before the argument type.
The Java main
method can also be declared using varargs.
public static void main(String[] args)
However, using varargs, it can also be declared as:
public static void main(String... args)
Both declarations are valid, and the JVM recognizes both as valid entry points for a Java application.
The args
parameter, whether declared as an array (String[]
) or as varargs (String...
), behaves as an array within the Java main
method. Here's an example:
public class VarargsMain {
public static void main(String... args) {
for (String arg : args) {
System.out.println(arg);
}
}
}
If you run this class with the command java VarargsMain Hello World
, the output will be:
Hello
World
Why Isn't Varargs Used More Often in main
?
The standard String[] args
is more commonly seen than the varargs version for a few reasons:
- Historical Precedence: Java's
main
method has traditionally usedString[] args
since before varargs were introduced (varargs came in Java 5). - Clarity: While
String... args
andString[] args
are functionally equivalent for themain
method, the array notation is more familiar to most Java developers. - Specific Use Case for Varargs: The primary benefit of varargs is when you have a method where you want to pass a variable number of arguments, potentially of different types. Since the
main
method always takes a sequence of strings, the traditional array notation is a clear and appropriate choice.
Why Java's Main Method is void?
The void
keyword in Java's main
method signature indicates that the method doesn't return any value. When looking at the signature:
public static void main(String[] args)
The use of void
might seem curious. However, the reasons for the main
method being void
in Java are grounded in design and utility.
The main
method serves as the entry point for the Java Virtual Machine (JVM) when executing a Java application. After this method finishes executing, the Java application typically terminates (unless there are non-daemon threads still running). If the main
method were to return a value, there would be a question of what the JVM would do with that returned value. In languages like C and C++, the main function returns an integer which can indicate the exit status of the program. However, Java took a different approach by handling program exit statuses using the System.exit(int status)
method, which allows any part of a Java application to terminate the program with a given status.
Java provides a more flexible mechanism for setting exit status or performing cleanup operations. The System.exit(int status)
method allows developers to exit from any part of the application and specify an exit status. Additionally, Java has a Runtime.addShutdownHook(Thread hook)
method, which lets you add a thread as a shutdown hook. This hook will execute when the JVM is shutting down, allowing you to perform cleanup operations.
Absence of Return in Main Method
In Java, the main
method's signature is defined as:
public static void main(String[] args)
Here, void
denotes that the main
method doesn't return any value. This might lead to the question: What happens if you try to return a value or if you don't provide any return statement?
Since the Java main
method is void
, you are not required to include a return statement, and even if you do, it cannot return any value. The presence or absence of a return
statement in a void
method does not affect the compilation or execution of the program.
In a void
method you can use a return statement by itself: This will simply exit the method prematurely.
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("No arguments provided.");
return;
}
System.out.println("Arguments provided.");
}
In the above example, if no command-line arguments are provided, the program will print "No arguments provided." and exit without printing the second statement.
If you try to return a value, like return 1;
, the compiler will throw an error because the main
method is declared as void
, which means it should not return any value.
Alternative Entry Points using the Java Launcher Tool
The traditional entry point for a Java application is the well-known public static void main(String[] args)
method. However, starting from Java 9 with the introduction of the Java Platform Module System (JPMS), you can specify alternative entry points using the Java launcher tool. This is especially useful when working with modular applications.
1. @PostConstruct
Annotation in Java EE:
In a Java EE (Enterprise Edition) environment, the @PostConstruct
annotation can be used to designate a method that should be executed after dependency injection is done. While this isn't a replacement for the Java main
method in standalone Java applications, it does serve as an entry point for initializing beans in a Java EE context.
2. Using the Provider
Interface with Modules:
With the JPMS in Java 9 and later, you can use the java.util.spi.ToolProvider
service provider interface to define custom tools that can be invoked by the Java launcher. Once you've defined a tool using this interface, you can run it using the Java launcher as follows:
java -m module.name/tool.name
Here, module.name
is the name of the module providing the tool, and tool.name
is the name of the tool.
3. public static int main(String[] args)
:
While it's not a standard practice, the Java launcher tool can invoke a Java main
method that returns an integer. This can serve as an alternative way to convey exit status directly from the main
method, similar to languages like C and C++.
4. JavaFX Application:
In a JavaFX application, the primary entry point is the start
method of the javafx.application.Application
class, not the traditional Java main
method. While you can still have a main
method in your JavaFX application, it's the start
method that's invoked by the JavaFX runtime to initialize and display the GUI.
Runtime Behavior Without a Main Method
In Java, the main
method serves as the standard entry point for standalone applications. When a Java class containing a Java main
method is executed using the Java interpreter, the JVM looks for this method to start the program. But what happens if this method is missing?
If There's No main
Method at All:
If you try to execute a class using the Java interpreter (using the java
command), and the class does not contain a Java main
method, the JVM will raise an error. The error message you'll get is:
Error: Main method not found in class ClassName, please define the main method as:
public static void main(String[] args)
or a JavaFX application class must extend javafx.application.Application
This indicates that the JVM couldn't find the standard entry point to start the application.
If the Java main
Method Has an Incorrect Signature:
The signature of the main
method is crucial. If the method is not public
, not static
, has a return type other than void
, or takes parameters other than String[]
, the JVM will consider it as an incorrect signature for the entry point.
For instance, if the main
method is not public
, you'll get an error like:
Error: Main method not public in class ClassName. Please define the main method as:
public static void main(String[] args)
Class with Constructors but Without main
:
If the class has constructors, but no Java main
method, and you try to run the class, the constructors won't be invoked. This is because constructors are called when an instance of the class is created, but the JVM doesn't create an instance of the class when you run it using the java
command. It just looks for the main
method to execute.
Can You Compile a Class Without main
?:
Yes, you can. The Java compiler (javac
) does not mandate the presence of the main
method in a class for it to be compiled. The requirement for the main
method is only enforced at runtime, not during compilation.
Runtime Behavior in Context of JavaFX:
JavaFX applications are an exception to this rule. In a JavaFX application, the primary entry point is the start
method of a class that extends javafx.application.Application
. If this method is present, you won't need a main
method to run the JavaFX application.
Main Method in Nested and Inner Classes
In Java, it's possible to define a main
method inside nested and inner classes, but invoking them is slightly different than with regular classes. Let's explore the possibilities:
1. Static Nested Class (often called a static inner class):
A static nested class is essentially a static member of the outer class. It can have static members, including the Java main
method.
public class OuterClass {
static class NestedStaticClass {
public static void main(String[] args) {
System.out.println("Main method in nested static class");
}
}
}
To run the main
method of NestedStaticClass
, you would use:
java OuterClass$NestedStaticClass
2. Inner (or Non-static Nested) Class:
Inner classes are associated with instances of the outer class and cannot have static members, except for constant variables (i.e., variables declared as static final
). Hence, you can't have a traditional Java main
method in a non-static inner class.
public class OuterClass {
class InnerClass {
// This will result in a compile-time error:
// public static void main(String[] args) { }
}
}
However, with some clever workarounds like using an initializer block and a System.exit(0)
, you can emulate a main
-like method, but this is not idiomatic and can be confusing.
3. Local Inner Class:
Local inner classes are defined inside a block, typically within a method. They can't have static members, so they can't have a Java main
method.
public class OuterClass {
void someMethod() {
class LocalInnerClass {
// Can't have a main method here.
}
}
}
4. Anonymous Inner Class:
Anonymous inner classes are, well, anonymous. They're typically used for overriding methods on the fly, especially with interfaces or abstract classes. They can't have named methods, so they certainly can't have a main
method.
public class OuterClass {
Runnable r = new Runnable() {
public void run() {
// Do something
}
// Can't have a main method here.
};
}
Main Method Execution Sequence & Initialization Blocks
The execution sequence of the Java main
method and initialization blocks in a Java class is an important concept, especially when it comes to understanding the initialization process of Java classes and objects. Here's a breakdown of the sequence:
1. Static Initialization Block:
Static initialization blocks are used for initializing static variables. These blocks get executed exactly once, when the class is loaded.
static {
System.out.println("Static Initialization Block");
}
2. Initialization Block (also called Instance Initialization Block):
These blocks are executed every time an instance of the class is created. They run before the constructor and after the call to super()
in the constructor.
{
System.out.println("Instance Initialization Block");
}
3. Constructors:
Constructors initialize objects. They run after the instance initialization blocks.
public MyClass() {
System.out.println("Constructor");
}
Execution Sequence:
- When you run a Java program, the class containing the
main
method is loaded into memory, triggering the static initialization block (if present). - Then, the Java
main
method is executed. - If, inside the
main
method (or as a result of it being run), you create an instance of the class or any other class, the sequence becomes a bit more detailed:
-
- First, any static initialization blocks of the class being instantiated will run (but only the first time an object of the class is created, because it's when the class is first loaded).
- Next, the instance initialization blocks run.
- Finally, the constructor of the class is executed.
Let's put everything together:
public class MyClass {
static {
System.out.println("Static Initialization Block");
}
{
System.out.println("Instance Initialization Block");
}
public MyClass() {
System.out.println("Constructor");
}
public static void main(String[] args) {
System.out.println("Main method");
MyClass obj = new MyClass();
}
}
When you run this program, the output will be:
Static Initialization Block
Main method
Instance Initialization Block
Constructor
Summary
When dealing with the main
method in Java and understanding the sequence of initialization, it's important to follow best practices and draw concrete conclusions from our exploration.
- Central Entry Point: The
main
method serves as the principal entry point for Java applications. It's where the Java Virtual Machine (JVM) starts execution. - Initialization Order Matters: The sequence of static and instance initialization blocks, constructors, and the
main
method is deterministic. This predictability helps developers ensure that dependencies and resources are initialized properly. - Versatility: Overloading the
main
method, using varargs, and understanding alternatives like the Java Launcher Tool give developers flexibility, but they also add complexity. It's essential to know when and why to use these features.
Best Practices
- Keep
main
Simple: Aim to keep themain
method concise and delegate tasks to other classes or methods. This helps in maintaining the code, making it more readable, and aids in unit testing. - Avoid Overloading for
main
: While it's possible to overload the Javamain
method, it's generally not recommended. It can create confusion, especially for newcomers or when reading someone else's code. - Initialization Order: Be aware of the initialization order (static blocks, instance blocks, constructors) to avoid null pointer exceptions or other runtime errors. Especially when static members depend on each other, their declaration order in the class can matter.
- Use
main
with Inner Classes Cautiously: While it's technically feasible to have amain
method in inner or nested classes, it can be confusing. If you decide to use it, document why to make it clear for other developers. - Respect Java Conventions: Stick to the standard signature
public static void main(String[] args)
. Even though the Java specification allows variations, sticking to conventions makes your code universally understandable. - Handle Exceptions: Always handle exceptions properly in the Java
main
method. A sudden termination due to an unhandled exception can be confusing for users. At the very least, have a generic exception handler that provides meaningful error messages.
Further Reading
Java main method
More about main method
Java methods