W3docs

Java Varargs (Argumentos de Comprimento Variável)

Defina métodos Java que aceitam qualquer número de argumentos com varargs (Type... name). Aprenda as regras, convenções de chamada, sobrecarga e armadilhas comuns.

Um parâmetro varargs (abreviação de variable-length arguments, argumentos de comprimento variável) permite que um método aceite qualquer número de argumentos — zero, um, dez, cem — do mesmo tipo, sem forçar o chamador a agrupá-los em um array primeiro. Você escreve o último parâmetro como Type... name, e dentro do método name é um array comum desse tipo.

Você já usou métodos varargs por anos. String.format("%s + %s = %s", a, b, c) aceita quantos valores de substituição a string de formato precisar. List.of(1, 2, 3, 4, 5) aceita uma lista arbitrária de elementos. Ambos dependem de varargs.

Declarando um parâmetro varargs

A sintaxe usa três pontos entre o tipo do elemento e o nome do parâmetro:

public static int sum(int... numbers) {
  int total = 0;
  for (int n : numbers) total += n;
  return total;
}

Os chamadores passam qualquer número de argumentos int:

sum();              // 0
sum(5);             // 5
sum(1, 2, 3);       // 6
sum(1, 2, 3, 4);    // 10

Dentro do método, numbers é um int[]. O compilador agrupa os argumentos avulsos em um array no ponto de chamada.

Varargs é apenas um array

O corpo trata o parâmetro varargs exatamente como um array — .length, indexação, for-each, tudo:

public static String join(String sep, String... parts) {
  if (parts.length == 0) return "";
  StringBuilder sb = new StringBuilder(parts[0]);
  for (int i = 1; i < parts.length; i++) {
    sb.append(sep).append(parts[i]);
  }
  return sb.toString();
}

join(", ", "red", "green", "blue");   // "red, green, blue"
join("-");                            // ""

Como o parâmetro é um array, você também pode passar um array literal diretamente:

String[] colors = {"red", "green", "blue"};
join(", ", colors);                   // same as join(", ", "red", "green", "blue")

O compilador aceita qualquer uma das formas.

As regras

Algumas restrições acompanham a sintaxe:

  • Um método pode ter no máximo um parâmetro varargs. Dois seriam ambíguos.
  • Ele deve ser o último parâmetro. Caso contrário, o compilador não conseguiria determinar onde os argumentos variáveis terminam e o próximo parâmetro começa.
  • Os outros parâmetros vêm primeiro. Parâmetros fixos na frente, varargs no final.
// VALID
public static String tag(String name, String... attrs)   { ... }
public static int    sum(int initial, int... rest)        { ... }

// INVALID
// public static int sum(int... a, int... b)              // two varargs
// public static int sum(int... a, int b)                 // varargs not last

Chamando métodos varargs

Você pode passar:

  1. Valores avulsosf(1, 2, 3).
  2. Um array do tipo corretof(new int[]{1, 2, 3}).
  3. Nadaf(). O método recebe um array de comprimento 0, não null.
sum();                       // numbers is int[0]
sum(new int[0]);             // also int[0]
sum(new int[]{1, 2, 3});     // numbers is int[]{1,2,3}

Um argumento null é um caso complicado: sum(null) compila, trata null como o próprio array, e o loop lança NullPointerException. A maioria dos métodos varargs não espera null.

Varargs e sobrecarga

Quando você sobrecarrega um método, as versões varargs são verificadas por último. Uma sobrecarga sem varargs (aridade fixa) que corresponder será preferida:

public static void show(int a, int b)    { System.out.println("two ints"); }
public static void show(int... xs)        { System.out.println("varargs"); }

show(1, 2);       // "two ints" — fixed-arity wins
show(1);          // "varargs"  — no fixed match
show(1, 2, 3);    // "varargs"

Isso é bom — varargs é o fallback, usado apenas quando nada mais específico se encaixa.

Uma armadilha comum: Object...

Varargs de Object aceita qualquer coisa, incluindo um array:

public static void log(Object... values) {
  for (Object v : values) System.out.println(v);
}

log("a", 1, 2.5);            // 3 calls
String[] names = {"Ada", "Bob"};
log(names);                   // ONE Object[] argument, prints "Ada" then "Bob"
log((Object) names);          // ONE Object argument, prints "[Ljava.lang.String;@..."

O compilador escolhe a interpretação que produz uma chamada válida. Com Object..., ambas as interpretações funcionam, e as regras favorecem "tratar o array como o array varargs." Se você quiser o array como um único elemento, faça o cast: log((Object) names).

Quando (não) usar varargs

Varargs é uma conveniência no ponto de chamada, não uma abstração gratuita. Cada chamada que passa valores avulsos aloca um novo array nos bastidores. Para métodos chamados em loops apertados em um caminho crítico, essa alocação pode acumular — é por isso que a biblioteca padrão às vezes oferece sobrecargas de aridade fixa junto com a versão varargs. List.of é o exemplo clássico: ele tem sobrecargas dedicadas para of(), of(e1), of(e1, e2) até dez elementos, e só recorre ao varargs of(E... elements) além disso.

Para código cotidiano, o custo é insignificante e a clareza prevalece. Use varargs quando:

  • o número de argumentos genuinamente varia (formatação, logging, construção de coleções);
  • forçar o chamador a escrever new Type[]{...} seria ruído.

Prefira um array simples ou um parâmetro List quando o chamador normalmente já possui uma coleção em mãos, ou quando você quer tornar "passar muitos valores" o caso explícito e esperado.

Um exemplo prático

java— editable, runs on the server

O que vem a seguir

Agora você pode escrever métodos com toda a gama de formas de parâmetros que Java oferece — fixos, sobrecarregados, recursivos e varargs. O capítulo final da parte de métodos retorna ao único método que todo programa tem: o método main — cujo String[] args pode igualmente ser escrito como String... args — e o que sua assinatura realmente diz à JVM.

Prática

Prática
Dentro de um método declarado como void f(int... xs), qual é o tipo de xs quando nenhum argumento é passado?
Dentro de um método declarado como void f(int... xs), qual é o tipo de xs quando nenhum argumento é passado?
Was this page helpful?