Menu

Varargs em Java: métodos que aceitam qualquer número de argumentos

Como os varargs (...) do Java permitem que um método aceite qualquer número de argumentos, como eles viram um array, a regra de um único vararg por último, e as armadilhas da chamada vazia e da ambiguidade.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

Um método, qualquer número de argumentos

Às vezes você não sabe de antemão quantos argumentos um método precisa. Num momento você quer max(3, 9) e no seguinte max(1, 7, 4, 2, 8). Sem varargs você teria que escrever uma sobrecarga para cada quantidade ou forçar quem chama a construir um array. Os varargs - abreviação de argumentos variáveis - permitem que um único método aceite zero, um ou muitos valores do mesmo tipo.

Você os declara colocando três pontos (...) depois do tipo do parâmetro:

Quem chama passa valores soltos; dentro do método numbers é um array de verdade. Essa é a ideia toda: o compilador empacota os argumentos em um array para você.

Varargs são apenas um array

Não há mágica em tempo de execução. Um parâmetro declarado int... numbers é exatamente um int[] quando você está dentro do método. Você pode consultar seu length, indexá-lo e percorrê-lo como qualquer outro array.

Como é genuinamente um array, você também pode entregar a um método varargs um array que já tem - ele aceita as duas formas:

As regras: por último e apenas um

Duas regras mantêm os varargs sem ambiguidade, e o compilador faz cumprir as duas:

  1. O parâmetro varargs precisa ser o último. Os parâmetros normais vêm primeiro, e então o parâmetro ... absorve tudo o que sobrar.
  2. Um método pode ter no máximo um parâmetro varargs. Dois tornariam impossível saber onde um termina e o próximo começa.

Isso compila. Mas colocar os varargs primeiro - static void log(Object... values, String level) - é um erro de compilação: varargs parameter must be the last. O parâmetro obrigatório level sempre precede o ....

Onde você já usa varargs

Você vem chamando métodos varargs o tempo todo. System.out.printf e String.format são os exemplos clássicos: o segundo parâmetro deles é Object... args:

List.of(...), Arrays.asList(...) e muitas APIs no estilo builder também são varargs. É por isso que você pode passar qualquer número de elementos para elas sem envolver nada em um array por conta própria.

Varargs e sobrecarga

Varargs e sobrecarga interagem de uma forma surpreendente. Quando uma sobrecarga normal e uma sobrecarga varargs poderiam ambas corresponder a uma chamada, o Java prefere a mais específica: o método de aridade fixa vence:

pick(1, 2) corresponde às duas, mas o Java escolhe a sobrecarga sem varargs porque ela encaixa melhor. O método varargs só é executado quando nenhuma sobrecarga de aridade fixa corresponde. Isso normalmente é o que você quer, mas significa que adicionar uma sobrecarga varargs pode mudar silenciosamente para qual método uma chamada é resolvida.

Cuidado com as chamadas vazias e com null

Duas armadilhas pegam as pessoas. Primeira: chamar um método varargs sem argumentos entrega ao método um array vazio, não null, então numbers.length é 0 e o laço não faz nada. Você não precisa de uma verificação de null para o caso sem argumentos:

Segunda: passar um null literal é ambíguo e perigoso: o Java pode interpretar count(null) como "o array de varargs inteiro é null" em vez de "um elemento null", o que então lança uma NullPointerException quando você lê seu length. Se você realmente quer dizer um único elemento null, seja explícito com count((Object) null).

A seguir: Classes

Os varargs completam o que você pode fazer com parâmetros de métodos: listas de argumentos flexíveis em cima da sobrecarga. Até agora os métodos viveram soltos em uma classe com static. A seguir você verá como as classes realmente funcionam: agrupar dados (campos) e comportamento (métodos) em seus próprios tipos, que é o coração da programação orientada a objetos em Java.

Perguntas frequentes

O que são varargs em Java?

Varargs (argumentos variáveis) permitem que um método aceite qualquer número de argumentos do mesmo tipo. Você os declara colocando ... depois do tipo: int sum(int... numbers). Quem chama pode passar zero, um ou muitos valores, e dentro do método numbers é um array normal. É açúcar sintático: o Java reúne os argumentos soltos em um array para você.

Um método em Java pode ter mais de um parâmetro varargs?

Não. Um método pode ter no máximo um parâmetro varargs, e ele precisa ser o último da lista de parâmetros - por exemplo void log(String level, Object... values). Se não fosse o último, o Java não saberia onde termina a parte de comprimento variável e onde começa o próximo parâmetro. Os parâmetros normais vêm sempre antes do parâmetro ....

Qual é a diferença entre varargs e um parâmetro de array em Java?

Eles são quase a mesma coisa em tempo de execução: um parâmetro varargs int... é um int[] dentro do método. A diferença está no ponto da chamada: com varargs você escreve sum(1, 2, 3) (valores soltos), enquanto com um parâmetro de array explícito você precisa construir e passar um array, sum(new int[]{1, 2, 3}). Um método varargs também aceita um array diretamente, então é a escolha mais flexível.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR