Introduction
Imagine you're giving instructions to a robot. You can either hardcode everything (boring!) or tell the robot what to do when it starts (flexible!). Command line arguments are like those startup instructions - they let you configure your Java program when you launch it!
Command line arguments allow you to pass information to your Java application at runtime, making your programs more dynamic and configurable without changing the source code.
What are Command Line Arguments?
Command line arguments are parameters provided to a program when it is executed. In Java, they are passed as an array of strings to the main method.
Basic Syntax:
public static void main(String[] args) {
// args contains command line arguments
}
Key Characteristics:
- β
String array: All arguments are passed as
Stringobjects - β Space-separated: Arguments are separated by spaces
- β Order matters: Arguments are accessed by their position
- β Quotes for spaces: Use quotes for arguments containing spaces
Code Explanation with Examples
Example 1: Basic Command Line Arguments
public class BasicArguments {
public static void main(String[] args) {
System.out.println("=== BASIC COMMAND LINE ARGUMENTS ===");
// π― Display all arguments
System.out.println("Number of arguments: " + args.length);
System.out.println("All arguments:");
for (int i = 0; i < args.length; i++) {
System.out.println(" args[" + i + "] = \"" + args[i] + "\"");
}
// π― Access specific arguments
if (args.length >= 1) {
System.out.println("\nFirst argument: " + args[0]);
}
if (args.length >= 2) {
System.out.println("Second argument: " + args[1]);
}
if (args.length >= 3) {
System.out.println("Third argument: " + args[2]);
}
// π― Simple argument-based logic
System.out.println("\n=== ARGUMENT-BASED LOGIC ===");
if (args.length == 0) {
System.out.println("No arguments provided. Using default behavior.");
System.out.println("Usage: java BasicArguments <name> <age> <city>");
} else if (args.length == 1) {
System.out.println("Hello, " + args[0] + "!");
} else if (args.length == 2) {
System.out.println("Hello, " + args[0] + "! You are " + args[1] + " years old.");
} else {
System.out.println("Hello, " + args[0] + "! You are " + args[1] +
" years old from " + args[2] + ".");
}
// π― Demonstration of different argument types
System.out.println("\n=== ARGUMENT TYPES DEMONSTRATION ===");
for (int i = 0; i < args.length; i++) {
String arg = args[i];
System.out.println("Argument " + i + " analysis:");
System.out.println(" Value: \"" + arg + "\"");
System.out.println(" Length: " + arg.length());
System.out.println(" Is numeric: " + isNumeric(arg));
System.out.println(" Is boolean: " + isBoolean(arg));
System.out.println(" Uppercase: " + arg.toUpperCase());
}
}
// Helper methods
private static boolean isNumeric(String str) {
try {
Double.parseDouble(str);
return true;
} catch (NumberFormatException e) {
return false;
}
}
private static boolean isBoolean(String str) {
return "true".equalsIgnoreCase(str) || "false".equalsIgnoreCase(str);
}
}
Run Examples:
# No arguments java BasicArguments # One argument java BasicArguments Alice # Multiple arguments java BasicArguments Bob 25 "New York" # Mixed types java BasicArguments 123 true "Hello World" 45.67
Output for java BasicArguments Bob 25 "New York":
=== BASIC COMMAND LINE ARGUMENTS === Number of arguments: 3 All arguments: args[0] = "Bob" args[1] = "25" args[2] = "New York" First argument: Bob Second argument: 25 Third argument: New York === ARGUMENT-BASED LOGIC === Hello, Bob! You are 25 years old from New York. === ARGUMENT TYPES DEMONSTRATION === Argument 0 analysis: Value: "Bob" Length: 3 Is numeric: false Is boolean: false Uppercase: BOB Argument 1 analysis: Value: "25" Length: 2 Is numeric: true Is boolean: false Uppercase: 25 Argument 2 analysis: Value: "New York" Length: 8 Is numeric: false Is boolean: false Uppercase: NEW YORK
Example 2: Advanced Argument Parsing Patterns
import java.util.*;
public class AdvancedArgumentParsing {
public static void main(String[] args) {
System.out.println("=== ADVANCED ARGUMENT PARSING ===");
// π― Pattern 1: Flag-based arguments (-f, --flag)
boolean verbose = false;
boolean help = false;
String outputFile = "output.txt";
int count = 1;
for (int i = 0; i < args.length; i++) {
switch (args[i]) {
case "-v":
case "--verbose":
verbose = true;
System.out.println("Verbose mode enabled");
break;
case "-h":
case "--help":
help = true;
break;
case "-o":
case "--output":
if (i + 1 < args.length) {
outputFile = args[++i];
System.out.println("Output file: " + outputFile);
} else {
System.out.println("Error: No output file specified after -o");
}
break;
case "-c":
case "--count":
if (i + 1 < args.length) {
try {
count = Integer.parseInt(args[++i]);
System.out.println("Count: " + count);
} catch (NumberFormatException e) {
System.out.println("Error: Invalid count value: " + args[i]);
}
}
break;
default:
// Handle positional arguments or unknown flags
if (args[i].startsWith("-")) {
System.out.println("Warning: Unknown option: " + args[i]);
} else {
System.out.println("Positional argument: " + args[i]);
}
}
}
// π― Display parsed configuration
System.out.println("\n=== PARSED CONFIGURATION ===");
System.out.println("Verbose: " + verbose);
System.out.println("Help: " + help);
System.out.println("Output file: " + outputFile);
System.out.println("Count: " + count);
if (help) {
displayHelp();
}
// π― Pattern 2: Key-value pairs (key=value)
System.out.println("\n=== KEY-VALUE PAIRS PARSING ===");
Map<String, String> config = parseKeyValueArgs(args);
System.out.println("Key-value configuration: " + config);
// π― Pattern 3: Subcommand pattern (like git commit, git push)
System.out.println("\n=== SUBCOMMAND PATTERN ===");
parseSubcommands(args);
}
private static void displayHelp() {
System.out.println("\n=== HELP ===");
System.out.println("Usage: java AdvancedArgumentParsing [OPTIONS]");
System.out.println("Options:");
System.out.println(" -v, --verbose Enable verbose output");
System.out.println(" -h, --help Display this help message");
System.out.println(" -o, --output FILE Set output file");
System.out.println(" -c, --count N Set operation count");
System.out.println(" key=value Set configuration key-value pairs");
}
private static Map<String, String> parseKeyValueArgs(String[] args) {
Map<String, String> config = new HashMap<>();
for (String arg : args) {
if (arg.contains("=")) {
String[] parts = arg.split("=", 2);
if (parts.length == 2) {
config.put(parts[0], parts[1]);
}
}
}
return config;
}
private static void parseSubcommands(String[] args) {
if (args.length == 0) {
System.out.println("No subcommand provided");
return;
}
String subcommand = args[0];
String[] subArgs = Arrays.copyOfRange(args, 1, args.length);
switch (subcommand) {
case "init":
System.out.println("Initializing with arguments: " + Arrays.toString(subArgs));
break;
case "build":
System.out.println("Building with arguments: " + Arrays.toString(subArgs));
break;
case "deploy":
System.out.println("Deploying with arguments: " + Arrays.toString(subArgs));
break;
default:
System.out.println("Unknown subcommand: " + subcommand);
System.out.println("Available subcommands: init, build, deploy");
}
}
}
Run Examples:
# Flag-based arguments java AdvancedArgumentParsing -v -o result.txt -c 5 # Mixed patterns java AdvancedArgumentParsing --verbose name=Alice age=25 city="New York" # Subcommand pattern java AdvancedArgumentParsing build --target production --clean
Output for java AdvancedArgumentParsing -v -o result.txt -c 5 name=Alice:
=== ADVANCED ARGUMENT PARSING ===
Verbose mode enabled
Output file: result.txt
Count: 5
Positional argument: name=Alice
=== PARSED CONFIGURATION ===
Verbose: true
Help: false
Output file: result.txt
Count: 5
=== KEY-VALUE PAIRS PARSING ===
Key-value configuration: {name=Alice}
=== SUBCOMMAND PATTERN ===
Unknown subcommand: -v
Available subcommands: init, build, deploy
Example 3: Real-World Application Configuration
import java.util.*;
public class AppConfiguration {
// Configuration fields
private String inputFile;
private String outputFile;
private boolean verbose;
private int maxLines;
private String logLevel;
private List<String> filters;
public static void main(String[] args) {
AppConfiguration config = new AppConfiguration();
config.parseArguments(args);
config.displayConfiguration();
if (config.isValid()) {
config.runApplication();
} else {
config.displayUsage();
}
}
public void parseArguments(String[] args) {
// Default values
inputFile = "input.txt";
outputFile = "output.txt";
verbose = false;
maxLines = 1000;
logLevel = "INFO";
filters = new ArrayList<>();
for (int i = 0; i < args.length; i++) {
try {
switch (args[i]) {
case "-i":
case "--input":
inputFile = args[++i];
break;
case "-o":
case "--output":
outputFile = args[++i];
break;
case "-v":
case "--verbose":
verbose = true;
break;
case "-m":
case "--max-lines":
maxLines = Integer.parseInt(args[++i]);
break;
case "-l":
case "--log-level":
logLevel = args[++i].toUpperCase();
break;
case "-f":
case "--filter":
filters.add(args[++i]);
break;
case "-h":
case "--help":
displayUsage();
System.exit(0);
break;
default:
if (args[i].startsWith("-")) {
System.err.println("Unknown option: " + args[i]);
} else {
// Treat as input file if not specified
if (inputFile.equals("input.txt")) {
inputFile = args[i];
} else {
System.err.println("Unexpected argument: " + args[i]);
}
}
}
} catch (ArrayIndexOutOfBoundsException e) {
System.err.println("Missing value for option: " + args[i]);
} catch (NumberFormatException e) {
System.err.println("Invalid number for option: " + args[i]);
}
}
}
public boolean isValid() {
if (maxLines <= 0) {
System.err.println("Error: max-lines must be positive");
return false;
}
if (!Arrays.asList("DEBUG", "INFO", "WARN", "ERROR").contains(logLevel)) {
System.err.println("Error: Invalid log level: " + logLevel);
return false;
}
return true;
}
public void displayConfiguration() {
System.out.println("=== APPLICATION CONFIGURATION ===");
System.out.println("Input file: " + inputFile);
System.out.println("Output file: " + outputFile);
System.out.println("Verbose mode: " + verbose);
System.out.println("Max lines: " + maxLines);
System.out.println("Log level: " + logLevel);
System.out.println("Filters: " + filters);
System.out.println();
}
public void displayUsage() {
System.out.println("=== USAGE ===");
System.out.println("java AppConfiguration [OPTIONS] [INPUT_FILE]");
System.out.println();
System.out.println("OPTIONS:");
System.out.println(" -i, --input FILE Input file (default: input.txt)");
System.out.println(" -o, --output FILE Output file (default: output.txt)");
System.out.println(" -v, --verbose Enable verbose output");
System.out.println(" -m, --max-lines N Maximum lines to process (default: 1000)");
System.out.println(" -l, --log-level LVL Log level: DEBUG, INFO, WARN, ERROR (default: INFO)");
System.out.println(" -f, --filter TEXT Add text filter (can be used multiple times)");
System.out.println(" -h, --help Display this help message");
System.out.println();
System.out.println("EXAMPLES:");
System.out.println(" java AppConfiguration data.txt");
System.out.println(" java AppConfiguration -i data.txt -o result.txt -v");
System.out.println(" java AppConfiguration --max-lines 5000 --log-level DEBUG");
}
public void runApplication() {
System.out.println("=== RUNNING APPLICATION ===");
System.out.println("Processing " + inputFile + " β " + outputFile);
if (verbose) {
System.out.println("Verbose: Processing with " + maxLines + " max lines");
System.out.println("Log level: " + logLevel);
if (!filters.isEmpty()) {
System.out.println("Applying filters: " + filters);
}
}
// Simulate some work
try {
for (int i = 1; i <= 3; i++) {
System.out.println("Working... (" + i + "/3)");
Thread.sleep(500);
}
System.out.println("β
Application completed successfully!");
} catch (InterruptedException e) {
System.err.println("Application interrupted");
}
}
}
Run Examples:
# Simple usage java AppConfiguration data.txt # Full configuration java AppConfiguration -i input.csv -o output.json -v -m 5000 -l DEBUG -f "error" -f "warning" # Help java AppConfiguration --help
Output for java AppConfiguration data.txt -v -m 2000:
=== APPLICATION CONFIGURATION === Input file: data.txt Output file: output.txt Verbose mode: true Max lines: 2000 Log level: INFO Filters: [] === RUNNING APPLICATION === Processing data.txt β output.txt Verbose: Processing with 2000 max lines Log level: INFO Working... (1/3) Working... (2/3) Working... (3/3) β Application completed successfully!
Example 4: Professional CLI Tool with Apache Commons CLI
// Note: This requires commons-cli library in classpath
// Download from: https://commons.apache.org/proper/commons-cli/
import org.apache.commons.cli.*;
public class ProfessionalCLI {
public static void main(String[] args) {
System.out.println("=== PROFESSIONAL CLI TOOL ===");
// π― Create Options object
Options options = new Options();
// π― Add options
options.addOption("h", "help", false, "Display help information");
options.addOption("v", "version", false, "Display version information");
options.addOption("i", "input", true, "Input file path");
options.addOption("o", "output", true, "Output file path");
options.addOption("l", "log-level", true, "Log level (DEBUG, INFO, WARN, ERROR)");
Option verbose = Option.builder("V")
.longOpt("verbose")
.desc("Enable verbose mode")
.build();
options.addOption(verbose);
Option maxLines = Option.builder("m")
.longOpt("max-lines")
.hasArg()
.argName("LINES")
.desc("Maximum lines to process")
.build();
options.addOption(maxLines);
// π― Parse command line
CommandLineParser parser = new DefaultParser();
HelpFormatter formatter = new HelpFormatter();
try {
CommandLine cmd = parser.parse(options, args);
// π― Handle options
if (cmd.hasOption("help")) {
formatter.printHelp("ProfessionalCLI", options, true);
return;
}
if (cmd.hasOption("version")) {
System.out.println("ProfessionalCLI v1.0.0");
return;
}
// π― Process application logic
String inputFile = cmd.getOptionValue("input", "default_input.txt");
String outputFile = cmd.getOptionValue("output", "default_output.txt");
String logLevel = cmd.getOptionValue("log-level", "INFO");
boolean isVerbose = cmd.hasOption("verbose");
int maxLinesValue = Integer.parseInt(cmd.getOptionValue("max-lines", "1000"));
// π― Display configuration
System.out.println("Configuration:");
System.out.println(" Input file: " + inputFile);
System.out.println(" Output file: " + outputFile);
System.out.println(" Log level: " + logLevel);
System.out.println(" Verbose: " + isVerbose);
System.out.println(" Max lines: " + maxLinesValue);
// π― Handle positional arguments
String[] positionalArgs = cmd.getArgs();
if (positionalArgs.length > 0) {
System.out.println("Positional arguments: " + Arrays.toString(positionalArgs));
}
// π― Run application
runApplication(inputFile, outputFile, isVerbose, maxLinesValue);
} catch (ParseException e) {
System.err.println("Error parsing command line: " + e.getMessage());
formatter.printHelp("ProfessionalCLI", options, true);
} catch (NumberFormatException e) {
System.err.println("Error: Invalid number format for max-lines");
}
}
private static void runApplication(String inputFile, String outputFile,
boolean verbose, int maxLines) {
System.out.println("\n=== EXECUTING APPLICATION ===");
if (verbose) {
System.out.println("Starting processing...");
System.out.println("Reading from: " + inputFile);
System.out.println("Writing to: " + outputFile);
System.out.println("Max lines: " + maxLines);
}
// Simulate processing
try {
for (int i = 1; i <= 5; i++) {
if (verbose) {
System.out.println("Processing batch " + i + "...");
}
Thread.sleep(300);
}
System.out.println("β
Processing completed successfully!");
System.out.println("Output saved to: " + outputFile);
} catch (InterruptedException e) {
System.err.println("Processing interrupted");
}
}
}
// Fallback version without external dependencies
class SimpleProfessionalCLI {
public static void main(String[] args) {
System.out.println("=== SIMPLE PROFESSIONAL CLI (No Dependencies) ===");
Map<String, String> config = parseArgs(args);
if (config.containsKey("help")) {
displayHelp();
return;
}
if (config.containsKey("version")) {
System.out.println("SimpleCLI v1.0.0");
return;
}
// Use configuration
String input = config.getOrDefault("input", "default.txt");
String output = config.getOrDefault("output", "output.txt");
boolean verbose = config.containsKey("verbose");
System.out.println("Input: " + input);
System.out.println("Output: " + output);
System.out.println("Verbose: " + verbose);
}
private static Map<String, String> parseArgs(String[] args) {
Map<String, String> config = new HashMap<>();
for (int i = 0; i < args.length; i++) {
switch (args[i]) {
case "-h":
case "--help":
config.put("help", "true");
break;
case "-v":
case "--version":
config.put("version", "true");
break;
case "-i":
case "--input":
if (i + 1 < args.length) config.put("input", args[++i]);
break;
case "-o":
case "--output":
if (i + 1 < args.length) config.put("output", args[++i]);
break;
case "-V":
case "--verbose":
config.put("verbose", "true");
break;
}
}
return config;
}
private static void displayHelp() {
System.out.println("Usage: SimpleProfessionalCLI [OPTIONS]");
System.out.println("Options:");
System.out.println(" -h, --help Show help");
System.out.println(" -v, --version Show version");
System.out.println(" -i, --input FILE Input file");
System.out.println(" -o, --output FILE Output file");
System.out.println(" -V, --verbose Enable verbose mode");
}
}
Run Examples:
# With Apache Commons CLI (if available) java -cp .:commons-cli-1.4.0.jar ProfessionalCLI -i data.txt -o result.json --verbose # Simple version (always works) java SimpleProfessionalCLI -i input.txt --verbose
Example 5: Error Handling and Validation
import java.util.*;
public class RobustArgumentParser {
private String inputFile;
private String outputFile;
private int port;
private boolean daemon;
private List<String> targets;
public static void main(String[] args) {
RobustArgumentParser parser = new RobustArgumentParser();
try {
parser.parse(args);
parser.validate();
parser.run();
} catch (IllegalArgumentException e) {
System.err.println("β Error: " + e.getMessage());
parser.displayUsage();
System.exit(1);
} catch (Exception e) {
System.err.println("β Unexpected error: " + e.getMessage());
System.exit(2);
}
}
public void parse(String[] args) {
// Default values
inputFile = null;
outputFile = "output.txt";
port = 8080;
daemon = false;
targets = new ArrayList<>();
if (args.length == 0) {
throw new IllegalArgumentException("No arguments provided");
}
for (int i = 0; i < args.length; i++) {
try {
switch (args[i]) {
case "-i":
case "--input":
requireValue(args, i);
inputFile = args[++i];
break;
case "-o":
case "--output":
requireValue(args, i);
outputFile = args[++i];
break;
case "-p":
case "--port":
requireValue(args, i);
port = parsePort(args[++i]);
break;
case "-d":
case "--daemon":
daemon = true;
break;
case "-t":
case "--target":
requireValue(args, i);
targets.add(args[++i]);
break;
case "-h":
case "--help":
displayUsage();
System.exit(0);
break;
default:
if (args[i].startsWith("-")) {
throw new IllegalArgumentException("Unknown option: " + args[i]);
} else {
// First non-option argument is input file
if (inputFile == null) {
inputFile = args[i];
} else {
throw new IllegalArgumentException("Unexpected argument: " + args[i]);
}
}
}
} catch (ArrayIndexOutOfBoundsException e) {
throw new IllegalArgumentException("Missing value for option: " + args[i]);
}
}
}
public void validate() {
List<String> errors = new ArrayList<>();
if (inputFile == null) {
errors.add("Input file is required");
}
if (port < 1 || port > 65535) {
errors.add("Port must be between 1 and 65535");
}
if (outputFile.trim().isEmpty()) {
errors.add("Output file cannot be empty");
}
if (!errors.isEmpty()) {
throw new IllegalArgumentException(String.join(", ", errors));
}
}
private void requireValue(String[] args, int currentIndex) {
if (currentIndex + 1 >= args.length) {
throw new IllegalArgumentException("Missing value for: " + args[currentIndex]);
}
}
private int parsePort(String portStr) {
try {
return Integer.parseInt(portStr);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid port number: " + portStr);
}
}
public void displayUsage() {
System.out.println("=== USAGE ===");
System.out.println("java RobustArgumentParser [OPTIONS] <input_file>");
System.out.println();
System.out.println("OPTIONS:");
System.out.println(" -i, --input FILE Input file (required)");
System.out.println(" -o, --output FILE Output file (default: output.txt)");
System.out.println(" -p, --port PORT Port number (1-65535, default: 8080)");
System.out.println(" -d, --daemon Run as daemon");
System.out.println(" -t, --target HOST Add target host (can be used multiple times)");
System.out.println(" -h, --help Display this help");
System.out.println();
System.out.println("EXAMPLES:");
System.out.println(" java RobustArgumentParser data.txt");
System.out.println(" java RobustArgumentParser -i data.txt -o result.json -p 9000");
System.out.println(" java RobustArgumentParser --input config.xml --daemon --target server1");
}
public void run() {
System.out.println("β
Configuration validated successfully!");
System.out.println();
System.out.println("=== STARTING APPLICATION ===");
System.out.println("Input file: " + inputFile);
System.out.println("Output file: " + outputFile);
System.out.println("Port: " + port);
System.out.println("Daemon mode: " + daemon);
System.out.println("Targets: " + targets);
System.out.println();
// Simulate application logic
System.out.println("π Application is running...");
if (daemon) {
System.out.println("π‘ Running in background (daemon mode)");
}
System.out.println("β
Application completed successfully!");
}
}
Run Examples:
# Valid usage java RobustArgumentParser data.txt -p 9090 -d # Error: Missing input file java RobustArgumentParser -p 9090 # Error: Invalid port java RobustArgumentParser data.txt -p 70000 # Error: Unknown option java RobustArgumentParser data.txt --unknown-option
Output for error case:
β Error: Input file is required === USAGE === java RobustArgumentParser [OPTIONS] <input_file> OPTIONS: -i, --input FILE Input file (required) -o, --output FILE Output file (default: output.txt) -p, --port PORT Port number (1-65535, default: 8080) -d, --daemon Run as daemon -t, --target HOST Add target host (can be used multiple times) -h, --help Display this help EXAMPLES: java RobustArgumentParser data.txt java RobustArgumentParser -i data.txt -o result.json -p 9000 java RobustArgumentParser --input config.xml --daemon --target server1
Command Line Argument Patterns
1. Simple Positional Arguments
java Program arg1 arg2 arg3
- β Simple and intuitive
- β Order matters, no self-documentation
2. Flag-Based Arguments
java Program -v --output file.txt --count 5
- β Self-documenting, order doesn't matter
- β More complex parsing required
3. Key-Value Pairs
java Program host=localhost port=8080 name="Server One"
- β Easy to parse, flexible
- β No standard format
4. Subcommand Pattern
java Program commit -m "message" java Program push origin main
- β Familiar (git-style), organized
- β Complex parsing logic
Best Practices
- Always provide help (
-hor--help) - Use both short and long options (
-vand--verbose) - Validate arguments and provide clear error messages
- Set sensible defaults for optional parameters
- Handle missing values gracefully
- Consider using libraries for complex CLIs (Apache Commons CLI, JCommander)
- Document your CLI with examples
- Support both
--option valueand--option=valuesyntax
Common Pitfalls
- Not handling missing required arguments
- Poor error messages that don't help users
- Assuming argument order without documentation
- Not validating numeric or format constraints
- Ignoring edge cases (quotes, special characters)
- Forgetting to handle
--help
Popular Libraries
- Apache Commons CLI - Mature, widely used
- JCommander - Annotation-based, clean API
- Picocli - Modern, feature-rich
- Args4j - Annotation-based, simple
Conclusion
Command line argument parsing is essential for building professional Java applications:
- β Makes applications configurable without code changes
- β Enables automation and scripting
- β Provides user-friendly interfaces for tools and utilities
- β Supports various use patterns from simple to complex
Key Takeaways:
String[] argsin main method receives command line arguments- Choose the right pattern for your application's complexity
- Always validate and provide helpful error messages
- Consider using libraries for professional-grade CLIs
- Document your command-line interface thoroughly
Remember: A well-designed command-line interface makes your Java applications more powerful, flexible, and user-friendly. Whether you're building simple scripts or complex enterprise tools, mastering command line argument parsing is a crucial skill!
Now you're ready to build Java applications that users can configure and control from the command line like a pro! π―π»