Java main method Explained [Easy Examples]


JAVA

Author: Bashir Alam
Reviewer: Deepak Prasad

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:

java main method

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:

java main method error

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.

java main method void

 

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:

command line

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:

command line run

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:

  1. Historical Precedence: Java's main method has traditionally used String[] args since before varargs were introduced (varargs came in Java 5).
  2. Clarity: While String... args and String[] args are functionally equivalent for the main method, the array notation is more familiar to most Java developers.
  3. 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:

  1. When you run a Java program, the class containing the main method is loaded into memory, triggering the static initialization block (if present).
  2. Then, the Java main method is executed.
  3. 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.

  1. 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.
  2. 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.
  3. 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

  1. Keep main Simple: Aim to keep the main 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.
  2. Avoid Overloading for main: While it's possible to overload the Java main method, it's generally not recommended. It can create confusion, especially for newcomers or when reading someone else's code.
  3. 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.
  4. Use main with Inner Classes Cautiously: While it's technically feasible to have a main 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.
  5. 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.
  6. 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

 

Bashir Alam

Bashir Alam

He is a Computer Science graduate from the University of Central Asia, currently employed as a full-time Machine Learning Engineer at uExel. His expertise lies in Python, Java, Machine Learning, OCR, text extraction, data preprocessing, and predictive models. You can connect with him on his LinkedIn profile.

Can't find what you're searching for? Let us assist you.

Enter your query below, and we'll provide instant results tailored to your needs.

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can send mail to admin@golinuxcloud.com

Thank You for your support!!

Leave a Comment