Java Argumentos da Linha de Comando

Desde o primeiro programa você escreve public static void main(String[] args). Agora dá para entender o String[] args: é um array de textos com as palavras que você escreve depois do nome do programa ao rodá-lo, como em java Main.java Ana 29. É outro jeito de dar informações ao programa, sem ele precisar perguntar.

Você vai aprender
  • O que é o args e como passar argumentos com java Main.java … e com java Main ….
  • Quantos argumentos chegaram: args.length.
  • Argumentos com espaço (aspas) e o curinga * do terminal.
  • Converter textos em números com Integer.parseInt e Double.parseDouble.
  • Os erros reais: ArrayIndexOutOfBoundsException (faltou argumento) e NumberFormatException (não é número).
  • Como escrever uma mensagem de uso, como os programas profissionais.
  • Quando usar argumentos e quando usar o Scanner.

Os exemplos rodam no terminal da Ana (máquina fictícia notebook, pasta ~/java, JDK 25).


A ideia antes do código

Há dois jeitos de pedir um café. No balcão, a atendente pergunta: "qual tamanho?", "com açúcar?", e você responde uma coisa de cada vez. Esse é o Scanner: o programa pergunta durante a execução. O outro jeito é entregar um bilhete já pronto: "café grande, sem açúcar". Ninguém precisa perguntar nada. Esses são os argumentos da linha de comando: você escreve tudo na mesma linha em que manda rodar o programa.

Você já usa isso o tempo todo no terminal. Em ls -l Documentos, o -l e o Documentos são argumentos do programa ls. Em javac Main.java, o Main.java é argumento do javac. Agora os seus programas também vão recebê-los.


Vendo o que chega no args

Este programa só mostra quantos argumentos recebeu e quais são:

public class Main {
    public static void main(String[] args) {
        System.out.println("Recebi " + args.length + " argumento(s)");
        for (int i = 0; i < args.length; i++) {
            System.out.println("args[" + i + "] = " + args[i]);
        }
    }
}
$ java Main.java Ana 29
Recebi 2 argumento(s)
args[0] = Ana
args[1] = 29
$ java Main.java
Recebi 0 argumento(s)        « sem argumentos, o array existe, mas está vazio
java
O lançador do Java.
Main.java
O programa a rodar. Não é um argumento do seu programa: é o que o java vai executar.
Ana
O primeiro argumento: vira args[0].
29
O segundo: vira args[1]. Repare: é o texto "29", não o número.

O terminal corta a linha nos espaços e o Java coloca cada pedaço numa posição do array, na ordem. Tudo o que você já sabe de arrays vale aqui: args.length é a quantidade, args[0] é o primeiro, e os índices começam no 0.

Por que args?

É a abreviação de arguments, "argumentos". É só um nome de variável: main(String[] parametros) também funciona. Mas args é a tradição, e todo programador Java reconhece.

Com javac e java separados

Se você compila antes (veja javac e java), os argumentos vêm depois do nome da classe:

$ javac Main.java
$ java Main Ana 29
Recebi 2 argumento(s)
args[0] = Ana
args[1] = 29
Nas IDEs

No IntelliJ, no Eclipse e no VS Code, os argumentos ficam na configuração de execução, num campo chamado "Program arguments" (argumentos do programa). Veja Editores e IDEs. No editor do guia, a caixa de código pode trazer os argumentos prontos, como nas missões abaixo.

Argumentos com espaço: aspas

Como o terminal separa nos espaços, um nome completo viraria dois argumentos. As aspas juntam (é a mesma regra do Bash; veja o Guia Bash, aula de aspas):

$ java Main.java "Ana Souza" 29
Recebi 2 argumento(s)
args[0] = Ana Souza          « um argumento só, com o espaço dentro
args[1] = 29
$ java Main.java 'R$ 10' 3,5 -v
Recebi 3 argumento(s)
args[0] = R$ 10
args[1] = 3,5
args[2] = -v

As aspas não chegam ao programa: elas são uma instrução para o terminal. E qualquer texto pode ser argumento, inclusive coisas como -v, que muitos programas usam como "opções".

O curinga *

Antes de rodar o programa, o terminal troca o * pelos nomes dos arquivos da pasta. Na pasta ~/java, só existe o Main.java:

$ java Main.java *
Recebi 1 argumento(s)
args[0] = Main.java          « o * virou o nome do arquivo
$ java Main.java 2 * 3
Recebi 3 argumento(s)
args[0] = 2
args[1] = Main.java          « era para ser o sinal de vezes!
args[2] = 3

O seu programa nunca vê o *. Para mandar o caractere de verdade, proteja com aspas ('*') ou barra invertida (\*). Por isso, em calculadoras de linha de comando, é comum usar x para multiplicar.


Usar os argumentos: converter para número

Todo argumento é uma String. Para fazer contas, converta com Integer.parseInt ("interpretar como inteiro"):

public class Main {
    public static void main(String[] args) {
        String nome = args[0];
        int idade = Integer.parseInt(args[1]);
        System.out.println("Olá, " + nome + "! Daqui a 10 anos você terá " + (idade + 10) + " anos.");
    }
}
$ java Main.java Ana 29
Olá, Ana! Daqui a 10 anos você terá 39 anos.
LinhaO que faz
String nome = args[0];O primeiro argumento já é texto: só copia para uma variável com um nome que explica o que ele é.
int idade = Integer.parseInt(args[1]);Transforma o texto "29" no número 29. Sem isso, args[1] + 10 daria "2910" (veja Concatenação).
(idade + 10)Agora é conta de verdade: 39.
Para obterUseAceita
intInteger.parseInt(texto)"29", "-3"
longLong.parseLong(texto)"9000000000"
doubleDouble.parseDouble(texto)"7.5": sempre com ponto, qualquer que seja o idioma do computador
booleanBoolean.parseBoolean(texto)"true" (qualquer outra coisa vira false)

Essas classes (Integer, Double…) são os "wrappers" dos tipos primitivos e têm uma aula própria: Wrappers e Autoboxing.

Missão: o programa é rodado com os argumentos Ana 29. Complete as duas linhas para ele mostrar Olá, Ana! Você tem 29 anos., usando args[0] e convertendo args[1] com Integer.parseInt.

public class Main {
    public static void main(String[] args) {
        String nome = "?";
        int idade = 0;
        System.out.println("Olá, " + nome + "! Você tem " + idade + " anos.");
    }
}
public class Main {
    public static void main(String[] args) {
        String nome = args[0];
        int idade = Integer.parseInt(args[1]);
        System.out.println("Olá, " + nome + "! Você tem " + idade + " anos.");
    }
}

Quando falta argumento: ArrayIndexOutOfBoundsException

O mesmo programa, rodado sem argumentos, ou com um só:

$ java Main.java
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0
	at Main.main(Main.java:3)
$ echo $?
1
$ java Main.java Ana
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 1 out of bounds for length 1
	at Main.main(Main.java:4)

É a mesma exceção da aula de Arrays. Sem argumentos, o args tem tamanho 0 (length 0), e a linha 3 pediu o índice 0. Com um argumento só, o tamanho é 1, e a linha 4 pediu o índice 1. O código de saída 1 (que o echo $? mostra) indica que o programa terminou com erro.

Quando não é número: NumberFormatException

$ java Main.java Ana vinte
Exception in thread "main" java.lang.NumberFormatException: For input string: "vinte"
	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
	at java.base/java.lang.Integer.parseInt(Integer.java:565)
	at java.base/java.lang.Integer.parseInt(Integer.java:662)
	at Main.main(Main.java:4)
$ java Main.java Ana 29.5
Exception in thread "main" java.lang.NumberFormatException: For input string: "29.5"
	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
	at java.base/java.lang.Integer.parseInt(Integer.java:565)
	at java.base/java.lang.Integer.parseInt(Integer.java:662)
	at Main.main(Main.java:4)
java.lang.NumberFormatException:
"Exceção de formato de número": o texto não tem o formato de um número daquele tipo.
For input string: "vinte"
"Para o texto de entrada "vinte"": a mensagem mostra exatamente o que foi recebido, entre aspas. Muito útil para descobrir espaços ou caracteres escondidos.
at java.base/…
Três linhas de dentro do próprio Java (o parseInt trabalhando).
at Main.main(Main.java:4)
A linha do seu código que chamou o parseInt. Comece sempre por ela.

"29.5" também falha: tem ponto, então não é um inteiro. Para decimais, use Double.parseDouble, que espera ponto: com "7,5" ele também lança NumberFormatException: For input string: "7,5" (conferido no laboratório).


A mensagem de uso

Programas de linha de comando bem-educados não explodem com uma exceção quando faltam argumentos: eles explicam como devem ser usados. Experimente javac sem nada: ele mostra como usá-lo. Vamos fazer o mesmo:

public class Main {
    public static void main(String[] args) {
        if (args.length != 2) {
            System.err.println("Uso: java Main.java NOME IDADE");
            System.err.println("Exemplo: java Main.java Ana 29");
            System.exit(1);
        }
        String nome = args[0];
        int idade = Integer.parseInt(args[1]);
        System.out.println("Olá, " + nome + "! Daqui a 10 anos você terá " + (idade + 10) + " anos.");
    }
}
$ java Main.java
Uso: java Main.java NOME IDADE
Exemplo: java Main.java Ana 29
$ echo $?
1                            « 1 = terminou com erro
$ java Main.java Ana 29
Olá, Ana! Daqui a 10 anos você terá 39 anos.
$ echo $?
0                            « 0 = tudo certo
LinhaO que faz
if (args.length != 2)Confere a quantidade antes de usar qualquer args[i].
System.err.println(…)Escreve na saída de erro (err = error), um canal separado da saída normal. No terminal, as duas aparecem iguais; mas quem redirecionar a saída para um arquivo (> resultado.txt) continua vendo o erro na tela. Veja print e println.
Uso: … NOME IDADEA convenção: a forma do comando, com as partes que o usuário troca em MAIÚSCULAS. Um exemplo concreto logo abaixo ajuda muito.
System.exit(1);Encerra o programa agora, com o código de saída 1. Por convenção, 0 é sucesso e qualquer outro número é erro. Sem esta linha, o programa continuaria e daria a exceção do mesmo jeito.

Argumentos opcionais

Nem todo argumento precisa ser obrigatório. Se não vier nada, use um valor padrão:

public class Main {
    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.println("Olá, visitante!");
        } else {
            System.out.println("Olá, " + args[0] + "!");
        }
    }
}
$ java Main.java
Olá, visitante!
$ java Main.java Ana
Olá, Ana!

Quantos argumentos vierem: o for-each

Como args é um array, um for-each passa por todos, sejam quantos forem:

public class Main {
    public static void main(String[] args) {
        int soma = 0;
        for (String arg : args) {
            soma += Integer.parseInt(arg);
        }
        System.out.println("Soma: " + soma);
    }
}
$ java Main.java 10 20 5
Soma: 35
$ java Main.java
Soma: 0                      « nenhuma volta: a soma ficou no valor inicial

Um exemplo completo: a calculadora

Três argumentos: número, operação, número. A escolha da operação usa o switch com setas:

public class Main {
    public static void main(String[] args) {
        double a = Double.parseDouble(args[0]);
        String op = args[1];
        double b = Double.parseDouble(args[2]);
        double resultado = switch (op) {
            case "+" -> a + b;
            case "-" -> a - b;
            case "x", "*" -> a * b;
            case "/" -> a / b;
            default -> {
                System.err.println("Operação desconhecida: " + op);
                System.exit(1);
                yield 0;
            }
        };
        System.out.println(a + " " + op + " " + b + " = " + resultado);
    }
}
$ java Main.java 7 x 3
7.0 x 3.0 = 21.0
$ java Main.java 7.5 / 2
7.5 / 2.0 = 3.75
$ java Main.java 7 % 2
Operação desconhecida: %
$ echo $?
1
$ java Main.java 7 * 3
Operação desconhecida: Main.java     « o terminal trocou o * pelo nome do arquivo
$ java Main.java 7 '*' 3
7.0 * 3.0 = 21.0

Para uma calculadora completa, com menu e validação, veja o projeto Calculadora.


Argumentos ou Scanner?

Argumentos (args)Scanner
Quando a informação chegaAntes de o programa começar, na linha do comandoDurante a execução, quando o programa pergunta
Tipo recebidoSempre String (converter com parseInt…)nextInt, nextDouble… já convertem
Ideal paraFerramentas e scripts: rodar várias vezes com dados diferentes, automatizarProgramas conversando com uma pessoa: menus, jogos, cadastros
Separador decimalDouble.parseDouble: sempre pontonextDouble: o do idioma do computador (vírgula em pt_BR)
Erros comunsArrayIndexOutOfBoundsException, NumberFormatExceptionInputMismatchException, NoSuchElementException

Muitos programas usam os dois: argumentos para as opções e o Scanner para conversar.


Quando dá errado

ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0

O que aconteceu: o programa usou args[0], mas foi rodado sem argumentos (length 0). Também acontece quando você roda pela IDE e esquece de preencher "Program arguments".

Como resolver: passe os argumentos (java Main.java Ana 29) e, no código, confira args.length antes de usar, mostrando uma mensagem de uso.

NumberFormatException: For input string: "…"

O que aconteceu: o texto entre aspas na mensagem não é um número do tipo pedido: letras ("vinte"), decimal num parseInt ("29.5") ou vírgula num parseDouble ("7,5"). Também acontece quando os argumentos estão na ordem errada (java Main.java 29 Ana).

Como resolver: confira a ordem e o formato; para pegar o erro sem o programa parar, use try/catch (try e catch).

Um argumento virou vários (ou o * virou nome de arquivo)

O que aconteceu: o terminal separa os argumentos nos espaços e expande os curingas (*, ?) antes de o Java receber qualquer coisa.

Como resolver: use aspas: "Ana Souza", '*'. Para conferir o que realmente chegou, rode o programa que lista os argumentos, do começo desta aula.

O argumento foi parar no lugar errado

Com javac + java, os argumentos vêm depois do nome da classe (java Main Ana, sem .java). No modo arquivo-fonte, depois do arquivo (java Main.java Ana). Opções do próprio Java (como -Xmx256m) vêm antes do nome; tudo o que vier depois do nome vai para o seu args.


Referência

Código ou comandoO que faz
java Main.java a b cRoda o arquivo-fonte com 3 argumentos
java Main a b cRoda a classe já compilada com 3 argumentos
args.lengthQuantidade de argumentos (0 se nenhum)
args[0]O primeiro argumento (sempre String)
for (String arg : args)Passa por todos
Integer.parseInt(args[1])Converte para int (NumberFormatException se não der)
Double.parseDouble(args[1])Converte para double (ponto decimal)
System.err.println("Uso: …")Mensagem de uso na saída de erro
System.exit(1)Encerra com código de erro
"Ana Souza", '*'No terminal: aspas protegem espaços e curingas

Exercícios

1. Quantos?

Complete para mostrar quantos argumentos o programa recebeu:

System.out.println();

2. Converter

Complete para transformar o terceiro argumento num int:

int quantidade =

3. Rodar

Complete o comando para passar o nome Ana Souza como um argumento só:

java Main.java

4. Com java Main.java 5 8, quanto vale args[0] + args[1]?

5. Rodando java Main.java sem nada, quanto vale args.length?

6. Qual o papel do System.exit(1) depois da mensagem de uso?

Missão final: o programa recebe vários números como argumentos (no teste: 17 42 8 23) e deve mostrar o maior deles: Maior: 42. Converta cada argumento com Integer.parseInt e use a receita do maior de Percorrer Arrays. Se quiser ir além, mostre uma mensagem de uso quando não vier nenhum número.

public class Main {
    public static void main(String[] args) {
        // encontre o maior argumento aqui
        int maior = 0;
        System.out.println("Maior: " + maior);
    }
}
public class Main {
    public static void main(String[] args) {
        if (args.length == 0) {
            System.err.println("Uso: java Main.java NÚMERO...");
            System.exit(1);
        }
        int maior = Integer.parseInt(args[0]);
        for (String arg : args) {
            int numero = Integer.parseInt(arg);
            if (numero > maior) {
                maior = numero;
            }
        }
        System.out.println("Maior: " + maior);
    }
}

Resumo

  • String[] args é um array com as palavras escritas depois do nome do programa: java Main.java Ana 29 → args[0] = "Ana", args[1] = "29".
  • args.length diz quantos vieram; sem argumentos, é 0 (o array existe, vazio).
  • Todo argumento é String: converta com Integer.parseInt, Double.parseDouble (ponto decimal)…
  • Faltou argumento: ArrayIndexOutOfBoundsException. Não é número: NumberFormatException: For input string: "…".
  • Confira args.length primeiro e mostre uma mensagem de uso com System.err + System.exit(1).
  • O terminal separa nos espaços e expande o * antes do Java: use aspas.