Java Tutorial
🔍

Java Command Line Arguments

Java Command Line Arguments

When you run a Java program, you can pass data to it directly from the terminal without prompting the user for input. That data comes in through the String[] args parameter you have written in the main method since your first Java program. Command line arguments are the mechanism behind this — they let external data reach your program at startup, before a single line of logic runs.

Every Java developer has written public static void main(String[] args) hundreds of times. Far fewer understand what args actually holds, how the JVM populates it, or why passing data this way is still common in production tooling, build scripts, and backend services. This article closes that gap.

What Are Command Line Arguments?

Command line arguments are values passed to a Java program when it is launched from the terminal or a script. They appear after the class name in the run command, separated by spaces. The JVM collects them into a String array and hands that array to your main method as the args parameter.

Every argument arrives as a String, regardless of whether you typed a number, a flag, or a file path. Parsing those strings into the types your program actually needs is your responsibility — the JVM delivers raw text.

The flow is straightforward:

java ClassName arg0 arg1 arg2
                |     |     |
                v     v     v
           args[0] args[1] args[2]

If no arguments are passed, args is not null — it is an empty array with length zero. This distinction matters whenever you check for arguments before using them.

Basic Syntax and Access

The entry point signature is fixed in Java. The args parameter is always a String[], and it is always named args by convention, though the name itself is not enforced by the compiler.

Java
1// File: HelloArgs.java 2 3public class HelloArgs { 4 5 public static void main(String[] args) { 6 7 System.out.println("Total arguments received: " + args.length); 8 9 for (int i = 0; i < args.length; i++) { 10 System.out.println("args[" + i + "] = " + args[i]); 11 } 12 } 13}

Run this from the terminal:

java HelloArgs Alice 25 Bangalore
Output:
Total arguments received: 3
args[0] = Alice
args[1] = 25
args[2] = Bangalore

The argument 25 is stored as the string "25", not the integer 25. If you need it as a number, you convert it explicitly with Integer.parseInt(args[1]).

Parsing Arguments to Correct Types

Since every argument arrives as a String, type conversion is a core part of working with command line input. The standard library conversion methods handle the common cases.

Java
1// File: TypeConversionDemo.java 2 3public class TypeConversionDemo { 4 5 public static void main(String[] args) { 6 7 if (args.length < 3) { 8 System.out.println("Usage: java TypeConversionDemo <name> <age> <salary>"); 9 return; 10 } 11 12 String name = args[0]; // already a String 13 int age = Integer.parseInt(args[1]); // "25" → 25 14 double salary = Double.parseDouble(args[2]); // "55000.50" → 55000.5 15 16 System.out.println("Name : " + name); 17 System.out.println("Age : " + age); 18 System.out.println("Salary : Rs." + salary); 19 } 20}
java TypeConversionDemo Priya 28 72500.0
Output:
Name   : Priya
Age    : 28
Salary : Rs.72500.0

The if (args.length < 3) guard is not optional. Without it, accessing args[1] on an empty args array throws an ArrayIndexOutOfBoundsException — one of the most common crashes in freshers' first Java programs.

Handling Spaces and Quoted Arguments

A space in the terminal separates one argument from the next. If you need to pass a value that contains spaces — a file path, a person's full name, a message — wrap it in double quotes.

java HelloArgs "Rahul Sharma" "Mumbai, Maharashtra" 30

The shell removes the quotes and passes the entire phrase as a single argument. Your Java code receives it as one element in args without the quotes.

Output:
Total arguments received: 3
args[0] = Rahul Sharma
args[1] = Mumbai, Maharashtra
args[2] = 30

This is a shell-level behavior, not a Java behavior. On Windows Command Prompt, double quotes work the same way.

Validating Arguments Properly

Production command line tools never assume the caller passed the right arguments in the right order. Input validation catches missing arguments, wrong types, and out-of-range values before they cause cryptic runtime failures deeper in the code.

Java
1// File: ArgumentValidator.java 2 3public class ArgumentValidator { 4 5 public static void main(String[] args) { 6 7 // Check argument count before accessing any index 8 if (args.length != 2) { 9 System.err.println("Error: expected exactly 2 arguments."); 10 System.err.println("Usage: java ArgumentValidator <employeeId> <basicSalary>"); 11 System.exit(1); // non-zero exit signals failure to the calling script 12 } 13 14 String employeeId = args[0]; 15 16 // Validate the numeric argument before parsing 17 double basicSalary; 18 try { 19 basicSalary = Double.parseDouble(args[1]); 20 } catch (NumberFormatException e) { 21 System.err.println("Error: '" + args[1] + "' is not a valid salary amount."); 22 System.exit(1); 23 return; // compiler needs this — System.exit throws at runtime, not compile time 24 } 25 26 if (basicSalary <= 0) { 27 System.err.println("Error: salary must be a positive value."); 28 System.exit(1); 29 } 30 31 double hra = basicSalary * 0.15; 32 double da = basicSalary * 0.10; 33 double gross = basicSalary + hra + da; 34 35 System.out.println("Employee ID : " + employeeId); 36 System.out.println("Basic : Rs." + basicSalary); 37 System.out.println("HRA : Rs." + hra); 38 System.out.println("DA : Rs." + da); 39 System.out.println("Gross : Rs." + gross); 40 } 41}
java ArgumentValidator EMP-042 45000
Output:
Employee ID : EMP-042
Basic       : Rs.45000.0
HRA         : Rs.6750.0
DA          : Rs.4500.0
Gross       : Rs.56250.0

System.err.println writes to the error stream rather than the standard output stream. This matters when the program is used in a shell pipeline — error messages on stderr do not corrupt the program's actual output on stdout.

Command Line Arguments vs Other Input Methods

Beginners often wonder when to use command line arguments versus Scanner, versus reading from a properties file. Each approach fits a different context.

FeatureCommand Line ArgumentsScanner (stdin)Properties File
When data is providedAt program startupWhile program runsAt startup (file read)
Interaction neededNoYesNo
Best forScripts, automation, CI/CDInteractive programsConfiguration values
Type safetyManual parsing requiredManual parsing requiredManual parsing required
Easy to change valuesYes — just rerun with new argsYes — type at promptRequires editing file
Visible in process listYes — args visible in psNoNo
Common use caseBuild tools, batch jobsUser-facing CLIsApp configuration

The "visible in process list" row is a real security concern. On Linux and macOS, running ps aux shows every process's command line including its arguments. Passing a password or API key as a command line argument exposes it to every user on the system. Use environment variables or a secrets file for sensitive values.

Real-World Example — Database Migration Tool

The Business Problem

Automated database migration scripts run in CI/CD pipelines at companies like Razorpay, Zepto, and PhonePe. These scripts connect to different database hosts depending on whether they are running in development, staging, or production. The environment, host, and schema name are not hardcoded — they are passed as command line arguments so the same compiled class can run in any environment.

Implementation

Java
1// File: MigrationConfig.java 2 3public class MigrationConfig { 4 5 public final String environment; 6 public final String dbHost; 7 public final String schemaName; 8 public final int port; 9 10 public MigrationConfig(String environment, String dbHost, 11 String schemaName, int port) { 12 this.environment = environment; 13 this.dbHost = dbHost; 14 this.schemaName = schemaName; 15 this.port = port; 16 } 17}
Java
1// File: DatabaseMigrationTool.java 2 3public class DatabaseMigrationTool { 4 5 private static final String[] VALID_ENVIRONMENTS = {"dev", "staging", "prod"}; 6 private static final int DEFAULT_PORT = 5432; 7 8 public static void main(String[] args) { 9 10 MigrationConfig config = parseArguments(args); 11 runMigration(config); 12 } 13 14 private static MigrationConfig parseArguments(String[] args) { 15 16 if (args.length < 3 || args.length > 4) { 17 printUsageAndExit(); 18 } 19 20 String environment = args[0].toLowerCase(); 21 String dbHost = args[1]; 22 String schemaName = args[2]; 23 int port = DEFAULT_PORT; 24 25 if (!isValidEnvironment(environment)) { 26 System.err.println("Error: environment must be dev, staging, or prod."); 27 System.err.println("Received: '" + environment + "'"); 28 System.exit(1); 29 } 30 31 if (args.length == 4) { 32 try { 33 port = Integer.parseInt(args[3]); 34 if (port < 1 || port > 65535) { 35 throw new NumberFormatException("Port out of range"); 36 } 37 } catch (NumberFormatException e) { 38 System.err.println("Error: '" + args[3] + "' is not a valid port number."); 39 System.exit(1); 40 } 41 } 42 43 if ("prod".equals(environment)) { 44 System.out.println("[WARN] Targeting PRODUCTION. Proceeding in 3 seconds..."); 45 try { 46 Thread.sleep(3000); 47 } catch (InterruptedException e) { 48 Thread.currentThread().interrupt(); 49 } 50 } 51 52 return new MigrationConfig(environment, dbHost, schemaName, port); 53 } 54 55 private static boolean isValidEnvironment(String env) { 56 for (String valid : VALID_ENVIRONMENTS) { 57 if (valid.equals(env)) return true; 58 } 59 return false; 60 } 61 62 private static void runMigration(MigrationConfig config) { 63 System.out.println("=== Database Migration Tool ==="); 64 System.out.println("Environment : " + config.environment.toUpperCase()); 65 System.out.println("Host : " + config.dbHost); 66 System.out.println("Schema : " + config.schemaName); 67 System.out.println("Port : " + config.port); 68 System.out.println("Connecting to " + config.dbHost + ":" + config.port + "/" + config.schemaName + "..."); 69 System.out.println("Running pending migrations..."); 70 System.out.println("Migration complete. 3 scripts applied."); 71 } 72 73 private static void printUsageAndExit() { 74 System.err.println("Usage: java DatabaseMigrationTool <env> <host> <schema> [port]"); 75 System.err.println(" env : dev | staging | prod"); 76 System.err.println(" host : database host (e.g., db.internal.razorpay.com)"); 77 System.err.println(" schema : schema name (e.g., payments_db)"); 78 System.err.println(" port : optional, defaults to 5432"); 79 System.exit(1); 80 } 81}
java DatabaseMigrationTool staging db.staging.internal payments_db 5433
Output:
=== Database Migration Tool ===
Environment : STAGING
Host        : db.staging.internal
Schema      : payments_db
Port        : 5433
Connecting to db.staging.internal:5433/payments_db...
Running pending migrations...
Migration complete. 3 scripts applied.

The optional fourth argument (port) demonstrates a common pattern: some arguments are mandatory, others are optional with sensible defaults. Checking args.length before each access handles both cases without error.

Running from IntelliJ IDEA

When running a program in IntelliJ, you pass arguments through the Run Configuration, not the terminal.

Go to Run → Edit Configurations → Program Arguments and type your arguments space-separated in the input field. IntelliJ passes them exactly as the terminal would. This is how most developers test command line programs during development without leaving the IDE.

Best Practices

Always check args.length before accessing any index. This is the single most important rule. An unchecked index access on an empty args array throws ArrayIndexOutOfBoundsException at runtime with no helpful message for the caller.

Print usage instructions on wrong input. When argument validation fails, show the caller what the correct format looks like before exiting. System.err.println is the right channel — it keeps usage messages separate from program output.

Use System.exit(1) for failure, System.exit(0) for success. Shell scripts and CI/CD pipelines check exit codes. A non-zero exit code signals failure and stops dependent pipeline steps from running. Returning normally from main exits with code 0 automatically.

Never pass sensitive data as command line arguments. Passwords, API keys, and tokens passed as arguments are visible in the process list to any user on the system. Use environment variables (System.getenv) or a secrets file for sensitive configuration.

Parse and validate early, use converted types throughout. Convert String arguments to their target types (int, double, boolean, enum) at the top of main, validate them immediately, then pass the strongly-typed values to the rest of the program. This prevents string parsing from scattering throughout your logic.

Common Mistakes

Mistake 1 — Accessing args[0] Without Checking args.length

Java
1public static void main(String[] args) { 2 // Crashes with ArrayIndexOutOfBoundsException when run with no arguments 3 System.out.println("Hello, " + args[0]); 4}

The fix is one line:

Java
1public static void main(String[] args) { 2 if (args.length == 0) { 3 System.out.println("Usage: java Greeter <name>"); 4 return; 5 } 6 System.out.println("Hello, " + args[0]); 7}

Mistake 2 — Assuming args Is Null When Empty

Java
1public static void main(String[] args) { 2 // This null check is unnecessary — args is never null 3 if (args == null || args.length == 0) { 4 System.out.println("No arguments provided."); 5 } 6}

The JVM always initialises args to an empty array when no arguments are passed. The null check is harmless but misleads the reader into thinking args could be null, which it cannot.

Mistake 3 — Forgetting to Handle NumberFormatException

Java
1public static void main(String[] args) { 2 // Crashes with NumberFormatException if args[0] is "abc" or empty 3 int count = Integer.parseInt(args[0]); 4 System.out.println("Count: " + count); 5}

Wrap any parseInt or parseDouble call in a try-catch when the source is user-controlled input. The terminal accepts any text — treating it as a guaranteed number is always wrong.

Interview Questions

Q1. What is String[] args in Java's main method?

String[] args is the parameter that receives command line arguments passed to the program at launch. Each space-separated token after the class name becomes one element in this array. The JVM populates it before calling main. If no arguments are passed, args is an empty array with length zero — it is never null.

Q2. What happens if no arguments are passed — is args null?

No. When a Java program is run with no arguments, args is an empty String[] with length 0, not null. Checking args == null is therefore unnecessary. The correct guard is args.length == 0 or checking for the specific minimum count the program requires.

Q3. Can you pass an integer directly as a command line argument?

No. Every command line argument arrives as a String, regardless of what was typed. To use a numeric argument as an int, you must parse it explicitly using Integer.parseInt(args[i]). If the string is not a valid integer, this throws NumberFormatException, which you should catch and handle with a useful error message.

Q4. What is the difference between System.out and System.err for command line programs?

System.out is the standard output stream — used for normal program output. System.err is the standard error stream — used for error messages, warnings, and usage instructions. When a program is used in a shell pipeline, separating error messages onto stderr ensures they do not corrupt the program's actual output data flowing through stdout.

Q5. Why should you never pass passwords as command line arguments?

Command line arguments are visible in the operating system's process list. On Linux and macOS, ps aux shows the full command line of every running process, including all arguments. Any user with access to the system can see them. For sensitive values like database passwords or API keys, use environment variables via System.getenv() or read from a protected secrets file.

Q6. How do you pass a multi-word argument that contains spaces?

Wrap the argument in double quotes in the terminal. The shell treats the quoted phrase as a single argument and strips the quotes before passing it to the JVM. Java receives the full phrase as one element in args without the surrounding quotes.

FAQs

Can a Java program modify its own command line arguments?

You can modify the args array within the program — reassigning args[0] changes the array element — but this has no effect outside the JVM. The original command line in the shell is not affected. Modifying args is generally a bad practice; use separate variables with meaningful names instead.

What is the maximum number of command line arguments allowed?

Java imposes no specific limit on the number of arguments. The practical limit comes from the operating system's maximum command line length, which is typically 32 KB on Linux and 8 KB on Windows. In practice, if you have so many arguments that you are near this limit, a configuration file is a better design.

How do I pass command line arguments in IntelliJ IDEA?

Open Run → Edit Configurations, select your run configuration, and enter your arguments space-separated in the Program Arguments field. Arguments with spaces should be quoted the same way you would quote them in a terminal. Click OK and run the program normally.

Can I use command line arguments with JAR files?

Yes. The syntax is: java -jar YourApp.jar arg1 arg2 arg3. Arguments after the JAR filename are passed to main exactly as they would be for a class. The -jar flag instructs the JVM to find the main class from the JAR's manifest file.

What is the difference between command line arguments and JVM arguments?

JVM arguments start with - or -X and configure the JVM itself — heap size, system properties, garbage collector settings (e.g., -Xmx512m, -Djava.util.logging.level=INFO). They appear before the class name or -jar. Command line arguments appear after the class name and are passed to your main method. They serve completely different purposes and travel through separate channels.

How do I read named arguments like --host=localhost instead of positional ones?

Java does not parse named arguments automatically. You write the parsing logic yourself: loop through args, check if each element starts with --, then split on = to extract the key and value. For complex CLI tools in production, libraries like Apache Commons CLI or picocli handle this properly with flags, defaults, and help text generation.

Summary

Command line arguments give a Java program its input before it starts. The JVM collects every token after the class name, wraps them in a String[], and passes that array to main as args. Every value arrives as a string — your code converts, validates, and uses them from there.

The mechanics are simple. The mistakes that cause real problems are all about skipping validation: assuming args has elements when it might be empty, assuming a string represents a valid number without checking, or assuming the caller always passes the right number of arguments. These assumptions cause crashes that are embarrassing in interviews and costly in production scripts.

For automated tools, migration scripts, and anything that runs in a CI/CD pipeline, command line arguments are the right mechanism. For interactive programs, Scanner suits better. For application configuration that changes between environments, a properties file or environment variables is the correct tool. Knowing which to reach for — and why — is what separates a thoughtful developer from someone who defaults to Scanner for everything.

What to Read Next

TopicLink
How Scanner reads user input at runtime and when to use it over argsJava Variables →
How arrays work in Java and how args fits the standard array modelJava Arrays →
How the JVM processes data types and why everything in args is a StringJava Data Types →
How exception handling catches NumberFormatException and invalid inputJava Exception Handling →
How the static keyword works and why main must always be staticJava static Keyword →
Java Command Line Arguments | DevStackFlow