BLOG POSTS
Command Line Arguments in Java: How to Use Them

Command Line Arguments in Java: How to Use Them

Command line arguments are parameters passed to a Java application when it starts, allowing you to customize program behavior without modifying the source code. They’re essential for creating flexible, production-ready applications that can adapt to different environments and configurations. This post will walk you through everything from basic argument handling to advanced parsing techniques, real-world implementation patterns, and troubleshooting common issues that developers encounter when deploying Java applications on servers.

How Command Line Arguments Work in Java

Java applications receive command line arguments through the main method’s String[] args parameter. When you execute a Java program, the JVM collects everything after the class name and passes it as an array of strings to your application.

public class ArgumentDemo {
    public static void main(String[] args) {
        System.out.println("Total arguments: " + args.length);
        for (int i = 0; i < args.length; i++) {
            System.out.println("Argument " + i + ": " + args[i]);
        }
    }
}

Running this with java ArgumentDemo hello world 123 produces:

Total arguments: 3
Argument 0: hello
Argument 1: world
Argument 2: 123

Key technical points to understand:

  • Arguments are always strings, regardless of input type
  • Spaces separate arguments unless enclosed in quotes
  • The JVM handles argument parsing before your code runs
  • Empty arguments array is valid when no parameters are provided
  • Arguments preserve order and can contain special characters

Step-by-Step Implementation Guide

Let's build a practical configuration utility that demonstrates proper argument handling:

import java.util.HashMap;
import java.util.Map;

public class ConfigManager {
    private Map config = new HashMap<>();
    
    public static void main(String[] args) {
        ConfigManager manager = new ConfigManager();
        manager.parseArguments(args);
        manager.displayConfiguration();
        manager.validateConfiguration();
    }
    
    private void parseArguments(String[] args) {
        for (int i = 0; i < args.length; i++) {
            if (args[i].startsWith("--")) {
                String key = args[i].substring(2);
                if (i + 1 < args.length && !args[i + 1].startsWith("--")) {
                    config.put(key, args[++i]);
                } else {
                    config.put(key, "true"); // Boolean flag
                }
            } else if (args[i].startsWith("-")) {
                String key = args[i].substring(1);
                if (i + 1 < args.length && !args[i + 1].startsWith("-")) {
                    config.put(key, args[++i]);
                } else {
                    config.put(key, "true");
                }
            }
        }
    }
    
    private void displayConfiguration() {
        System.out.println("Configuration loaded:");
        config.forEach((key, value) -> 
            System.out.println("  " + key + " = " + value));
    }
    
    private void validateConfiguration() {
        if (config.containsKey("port")) {
            try {
                int port = Integer.parseInt(config.get("port"));
                if (port < 1 || port > 65535) {
                    System.err.println("Invalid port range: " + port);
                    System.exit(1);
                }
            } catch (NumberFormatException e) {
                System.err.println("Port must be numeric");
                System.exit(1);
            }
        }
    }
}

Usage examples:

java ConfigManager --host localhost --port 8080 --debug
java ConfigManager -h 192.168.1.100 -p 9090 --ssl-enabled

This implementation handles both long-form (--option) and short-form (-o) arguments, boolean flags, and includes basic validation.

Real-World Examples and Use Cases

Here are practical scenarios where command line arguments prove invaluable:

Database Connection Manager

public class DatabaseConnector {
    private String host = "localhost";
    private int port = 5432;
    private String database = "production";
    private String username;
    private String password;
    private boolean useSSL = false;
    
    public static void main(String[] args) {
        DatabaseConnector connector = new DatabaseConnector();
        connector.processArguments(args);
        connector.connect();
    }
    
    private void processArguments(String[] args) {
        for (int i = 0; i < args.length; i++) {
            switch (args[i]) {
                case "--host":
                    host = args[++i];
                    break;
                case "--port":
                    port = Integer.parseInt(args[++i]);
                    break;
                case "--database":
                    database = args[++i];
                    break;
                case "--username":
                    username = args[++i];
                    break;
                case "--password":
                    password = args[++i];
                    break;
                case "--ssl":
                    useSSL = true;
                    break;
                case "--help":
                    printUsage();
                    System.exit(0);
                    break;
            }
        }
    }
    
    private void printUsage() {
        System.out.println("Usage: java DatabaseConnector [OPTIONS]");
        System.out.println("Options:");
        System.out.println("  --host HOST        Database host (default: localhost)");
        System.out.println("  --port PORT        Database port (default: 5432)");
        System.out.println("  --database DB      Database name (default: production)");
        System.out.println("  --username USER    Database username");
        System.out.println("  --password PASS    Database password");
        System.out.println("  --ssl              Enable SSL connection");
        System.out.println("  --help             Show this help message");
    }
}

Log File Processor

public class LogProcessor {
    public static void main(String[] args) {
        if (args.length < 2) {
            System.err.println("Usage: java LogProcessor   [options]");
            System.exit(1);
        }
        
        String inputFile = args[0];
        String outputFile = args[1];
        String logLevel = "INFO";
        String dateFormat = "yyyy-MM-dd";
        
        // Process optional arguments
        for (int i = 2; i < args.length; i++) {
            if ("--level".equals(args[i]) && i + 1 < args.length) {
                logLevel = args[++i];
            } else if ("--date-format".equals(args[i]) && i + 1 < args.length) {
                dateFormat = args[++i];
            }
        }
        
        System.out.println("Processing: " + inputFile + " -> " + outputFile);
        System.out.println("Log level: " + logLevel);
        System.out.println("Date format: " + dateFormat);
    }
}

Comparison with Argument Parsing Libraries

While manual argument parsing works for simple cases, libraries offer more robust solutions:

Method Complexity Features Dependencies Best For
Manual Parsing Low Basic None Simple applications, learning
Apache Commons CLI Medium Rich validation, help generation External JAR Enterprise applications
JCommander Medium Annotation-based, type conversion External JAR Complex command structures
Picocli Medium-High ANSI colors, subcommands, completion External JAR Modern CLI applications

Apache Commons CLI Example

import org.apache.commons.cli.*;

public class CommonsCliExample {
    public static void main(String[] args) {
        Options options = new Options();
        
        options.addOption("h", "host", true, "Database host");
        options.addOption("p", "port", true, "Database port");
        options.addOption("d", "database", true, "Database name");
        options.addOption("v", "verbose", false, "Enable verbose output");
        
        CommandLineParser parser = new DefaultParser();
        HelpFormatter formatter = new HelpFormatter();
        
        try {
            CommandLine cmd = parser.parse(options, args);
            
            String host = cmd.getOptionValue("host", "localhost");
            int port = Integer.parseInt(cmd.getOptionValue("port", "5432"));
            String database = cmd.getOptionValue("database", "mydb");
            boolean verbose = cmd.hasOption("verbose");
            
            System.out.println("Connecting to: " + host + ":" + port + "/" + database);
            if (verbose) {
                System.out.println("Verbose mode enabled");
            }
            
        } catch (ParseException e) {
            System.err.println("Parsing failed: " + e.getMessage());
            formatter.printHelp("DatabaseApp", options);
        }
    }
}

Best Practices and Common Pitfalls

Security Considerations

  • Never pass sensitive data like passwords directly as arguments - they appear in process lists
  • Use configuration files or environment variables for secrets
  • Validate and sanitize all input arguments
  • Implement proper error handling to avoid information disclosure
// DON'T DO THIS
java MyApp --password secretpass123

// DO THIS INSTEAD
java MyApp --config-file /secure/config.properties
// or use environment variables
String password = System.getenv("DB_PASSWORD");

Error Handling Best Practices

public class RobustArgumentParser {
    public static void parsePort(String portArg) {
        try {
            int port = Integer.parseInt(portArg);
            if (port < 1 || port > 65535) {
                throw new IllegalArgumentException("Port must be between 1 and 65535");
            }
            return port;
        } catch (NumberFormatException e) {
            System.err.println("Error: Port must be a valid number, got: " + portArg);
            System.exit(1);
        } catch (IllegalArgumentException e) {
            System.err.println("Error: " + e.getMessage());
            System.exit(1);
        }
        return -1; // Never reached
    }
}

Performance Considerations

Argument parsing typically has minimal performance impact, but consider these points for high-performance applications:

  • Parse arguments once during initialization, not repeatedly
  • Use appropriate data structures for lookups (HashMap for key-value pairs)
  • Cache parsed values instead of re-parsing strings
  • Validate early to fail fast and avoid expensive operations

Advanced Usage Patterns

Configuration Hierarchy

public class ConfigurationManager {
    private Properties config = new Properties();
    
    public void loadConfiguration(String[] args) {
        // 1. Load default configuration
        loadDefaults();
        
        // 2. Load from configuration file
        String configFile = findConfigFile(args);
        if (configFile != null) {
            loadFromFile(configFile);
        }
        
        // 3. Override with command line arguments (highest priority)
        overrideFromArgs(args);
    }
    
    private String findConfigFile(String[] args) {
        for (int i = 0; i < args.length - 1; i++) {
            if ("--config".equals(args[i])) {
                return args[i + 1];
            }
        }
        return null;
    }
}

Handling Complex Argument Structures

// Support for: java MyApp server --port 8080 --threads 10
public class SubcommandParser {
    public static void main(String[] args) {
        if (args.length == 0) {
            printUsage();
            return;
        }
        
        String command = args[0];
        String[] commandArgs = Arrays.copyOfRange(args, 1, args.length);
        
        switch (command) {
            case "server":
                startServer(commandArgs);
                break;
            case "client":
                startClient(commandArgs);
                break;
            case "migrate":
                runMigration(commandArgs);
                break;
            default:
                System.err.println("Unknown command: " + command);
                printUsage();
        }
    }
}

Environment Integration

For applications deployed on VPS or dedicated servers, combine command line arguments with environment variables:

public class EnvironmentAwareConfig {
    public static String getConfigValue(String key, String[] args, String defaultValue) {
        // Priority: Command line -> Environment -> Default
        String cliValue = extractFromArgs(key, args);
        if (cliValue != null) return cliValue;
        
        String envValue = System.getenv(key.toUpperCase().replace("-", "_"));
        if (envValue != null) return envValue;
        
        return defaultValue;
    }
    
    private static String extractFromArgs(String key, String[] args) {
        String flag = "--" + key;
        for (int i = 0; i < args.length - 1; i++) {
            if (flag.equals(args[i])) {
                return args[i + 1];
            }
        }
        return null;
    }
}

Troubleshooting Common Issues

Argument Parsing Problems

Common issues and solutions:

  • Spaces in arguments: Use quotes or escape characters
  • Special characters: Properly escape shell metacharacters
  • Encoding issues: Ensure consistent character encoding
  • Array bounds: Always check array length before accessing elements
// Handle problematic input safely
public class SafeArgumentParser {
    public static String getArgumentValue(String[] args, String flag) {
        for (int i = 0; i < args.length - 1; i++) {
            if (flag.equals(args[i])) {
                String value = args[i + 1];
                if (value.startsWith("-")) {
                    throw new IllegalArgumentException("Missing value for " + flag);
                }
                return value;
            }
        }
        return null;
    }
}

Debugging Argument Issues

public class ArgumentDebugger {
    public static void debugArguments(String[] args) {
        System.out.println("=== Argument Debug Information ===");
        System.out.println("Total arguments: " + args.length);
        
        for (int i = 0; i < args.length; i++) {
            System.out.printf("args[%d] = '%s' (length: %d)%n", 
                            i, args[i], args[i].length());
            
            // Show non-printable characters
            for (char c : args[i].toCharArray()) {
                if (c < 32 || c > 126) {
                    System.out.printf("  Contains non-printable char: %d%n", (int)c);
                }
            }
        }
        System.out.println("=== End Debug Information ===");
    }
}

Command line arguments are fundamental to creating professional Java applications that integrate well with system administration workflows and deployment pipelines. The techniques covered here provide a solid foundation for building robust, configurable applications whether you're deploying simple utilities or complex enterprise systems. For more advanced command line interface development, consider exploring the Apache Commons CLI documentation or the Picocli framework for modern CLI applications with enhanced features.



This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.

This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.

Leave a reply

Your email address will not be published. Required fields are marked