main, and the arguments it is handed
Why the signature is exactly that, what the JVM passes you, and what the shell did to it first.
public static void main(String[] args)Every word of that is required, and each one is required for a reason. Getting one wrong produces a program that compiles perfectly and will not start.
Why each word
public — the JVM has to call it from outside your class. Anything narrower and it cannot.
static — it is called before any object exists. The JVM has your class and nothing else; there is no instance for it to call a method on, so the method must belong to the class itself.
void — nothing meaningful could receive a return value. (The process's exit code comes from System.exit or from finishing normally, not from main.)
main — the name the JVM looks for. Not configurable.
String[] args — what you were invoked with. The type and the fact that it is an array are fixed; the name is not, and String... args works too because varargs is an array underneath.
Change any of the first four and you get this:
Error: Main method not found in class Greet, please define the main method as:
public static void main(String[] args)Which is an unusually helpful error, because it prints the thing you needed.
What the JVM hands you
public class Greet {
public static void main(String[] args) {
System.out.println("args.length = " + args.length);
for (int i = 0; i < args.length; i++)
System.out.println(" args[" + i + "] = " + args[i]);
}
}$ java Greet
args.length = 0
$ java Greet hello world "two words"
args.length = 3
args[0] = hello
args[1] = world
args[2] = two wordsThree things worth noticing, because each is a place people are wrong:
The array is empty, never null. java Greet with no arguments gives you a zero-length array. args == null is a check you do not need and will never fire.
The program name is not in it. In C, argv[0] is the program. In Java, args[0] is the first argument. There is no slot for the class name.
The shell split them, not Java. "two words" arrived as one argument because the shell removed the quotes and passed a single string. Java received three strings and has no idea quotes were involved. This is why a path with a space in it breaks a script that forgot to quote a variable — the splitting already happened before your code ran.
What arguments are, and are not, for
They are fine for a small program, a script, a one-off tool.
For a service, configuration goes in the environment rather than in arguments, for the reasons the foundations course gives: the same artifact runs everywhere and only its environment differs. You will see Spring Boot accept both — --server.port=8081 as an argument and SERVER_PORT=8081 as a variable — and the environment is the one that survives a container.
And secrets never go in arguments. Anything on a command line is visible to ps for anyone on the machine.
More than one main
Any class can have a main. That is not a mistake — it is how a project ends up with several entry points, and how people put a quick test harness inside a class.
Which one runs is decided entirely by what you name on the command line:
java com.shop.Order # runs Order's main
java com.shop.Report # runs Report's mainA jar can declare a default in its manifest, which is what lets java -jar app.jar work without naming a class. That is the build tool's business, and the next lesson touches where things live.
Try it yourself
Find out what arrives
Write the program above, then:
- Run it with no arguments. Is
argsnull or empty? - Pass three words. Pass one quoted phrase. What is the difference in
args.length? - Pass
--name=Alice. How many arguments, and what is in them? - Rename
maintoMainand run it. What exactly does the error say? - Remove
staticand run it. Same error, or different?
What you learn
- Empty, length 0. Never null.
- Three words → 3. One quoted phrase → 1. The shell decided, before Java saw anything.
- One argument, the literal string
--name=Alice. No parsing happened. - and 5. The same error both times — "Main method not found… please define the main method as:
public static void main(String[] args)". The JVM is looking for a method matching that exact signature; a wrong name and a missingstaticboth mean it is not there, and it cannot tell you which you got wrong. That is why the message just prints the correct form.