Java, 3 pontos em parâmetros

822

O que significam os 3 pontos no método a seguir?

public void myMethod(String... strings){
    // method body
}
Vikram
fonte

Respostas:

987

Isso significa que zero ou mais objetos String (ou uma matriz deles) podem ser passados ​​como argumento (s) para esse método.

Consulte a seção "Número arbitrário de argumentos" aqui: http://java.sun.com/docs/books/tutorial/java/javaOO/arguments.html#varargs

No seu exemplo, você pode chamá-lo como qualquer um dos seguintes:

myMethod(); // Likely useless, but possible
myMethod("one", "two", "three");
myMethod("solo");
myMethod(new String[]{"a", "b", "c"});

Nota importante: Os argumentos passados ​​dessa maneira são sempre uma matriz - mesmo que exista apenas uma. Certifique-se de tratá-lo dessa maneira no corpo do método.

Nota importante 2: O argumento que obtém o ...deve ser o último na assinatura do método. Então, myMethod(int i, String... strings)está tudo bem, mas myMethod(String... strings, int i)não está bem.

Agradecemos a Vash pelos esclarecimentos em seu comentário.

kiswa
fonte
112
Você está enganado, em que "um ou mais", com varargs, podemos especificar 0 ou mais, e esse deve ser sempre o último parâmetro no método. O método x (String ... params) pode ser chamada como x () ou método y (String carrinho de bebê, String ... params) pode ser chamada como y ( "1")
Damian Leszczyński - Vash
2
Eu gostaria que isso tivesse funcionado também. myMethod ("um", "dois", "três", nova String [] {"a", "b", "c" "});
2sb
2
Por que você tem permissão para fornecer ao método 0 parâmetros? Isso provavelmente levará a ArrayIndexOutOfBoundsException. Agora você sempre deve levar esse caso em consideração.
Olle Söderström
11
Porque eles são opcionais. Cabe ao desenvolvedor que decidiu usar argumentos opcionais para implementar adequadamente o método para lidar com zero ou mais deles.
Kiswa 16/05
@ OlleSöderström Outro motivo é que o parâmetro formal é convertido para ser uma matriz em tempo de compilação. Isso significa que passar em uma matriz produz o mesmo resultado. Como o comprimento de uma matriz não é conhecido em tempo de compilação, a restrição para passar pelo menos um elemento pode ser ignorada simplesmente chamando someMethod(new SomeType[] { }). Isso seria um truque, não?
MC Emperor
124

Esse recurso é chamado varargs e é um recurso introduzido no Java 5. Isso significa que a função pode receber vários Stringargumentos:

myMethod("foo", "bar");
myMethod("foo", "bar", "baz");
myMethod(new String[]{"foo", "var", "baz"}); // you can even pass an array

Em seguida, você pode usar o Stringvar como uma matriz:

public void myMethod(String... strings){
    for(String whatever : strings){
        // do what ever you want
    }

    // the code above is is equivalent to
    for( int i = 0; i < strings.length; i++){
        // classical for. In this case you use strings[i]
    }
}

Esta resposta empresta fortemente os de Kiswa e Lorenzo ... e também do comentário do Graphain.

Cristian
fonte
13
Quando o código atinge o bytecode, é uma matriz. Tudo o resto é suportado por sintaxe apenas pelo compilador.
Donal Fellows
Essa resposta empresta muito do kiswa e do Lorenzo, se eu ler as edições corretamente.
Matt Mitchell
3
@Graph é melhor editar sua resposta e torná-la mais correta do que deixá-la em paz. E se outra resposta é a fonte da sua melhoria, ele continua. Pelo menos ele é honesto sobre isso (e eu suponho que ele votou nas outras respostas que o ajudaram ... certo?).
1
@Will ele é honesto depois que eu indiquei o que é bom o suficiente. Obrigado por procurar.
23410 Matt Mitchell
23

É Varargs :)

O varargs abreviação de argumentos de tamanho variável é um recurso que permite que o método aceite número variável de argumentos (zero ou mais). Com varargs, tornou-se simples criar métodos que precisam receber um número variável de argumentos. O recurso de argumento variável foi adicionado no Java 5.

Sintaxe de varargs

Um vararg é seccionado por três reticências (três pontos) após o tipo de dados, sua forma geral é

return_type method_name(data_type ... variableName){
}  

Necessidade de varargs

Antes do Java 5, caso houvesse necessidade de número variável de argumentos, havia duas maneiras de lidar com isso

Se o número máximo de argumentos que um método pode assumir for pequeno e conhecido, poderão ser criadas versões sobrecarregadas do método. Se o número máximo de argumentos que um método poderia levar era grande ou desconhecido e, em seguida, a abordagem era colocar esses argumentos em uma matriz e passá-los para um método que toma a matriz como parâmetro. Essas duas abordagens eram propensas a erros - construindo sempre uma matriz de parâmetros e difíceis de manter -, pois a adição de novos argumentos pode resultar na escrita de um novo método sobrecarregado.

Vantagens de varargs

Oferece uma opção muito mais simples. Menos código, pois não é necessário escrever métodos sobrecarregados.

Exemplo de varargs

public class VarargsExample {
 public void displayData(String ... values){
  System.out.println("Number of arguments passed " + values.length);
  for(String s : values){
   System.out.println(s + " ");
  }
 }

 public static void main(String[] args) {
  VarargsExample vObj = new VarargsExample();
  // four args
  vObj.displayData("var", "args", "are", "passed");
  //three args
  vObj.displayData("Three", "args", "passed");
  // no-arg
  vObj.displayData();
 }
}
Output

Number of arguments passed 4
var 
args 
are 
passed 
Number of arguments passed 3
Three 
args 
passed 
Number of arguments passed 0

Pode ser visto no programa que o comprimento é usado aqui para encontrar o número de argumentos passados ​​para o método. É possível porque os varargs são passados ​​implicitamente como uma matriz. Quaisquer que sejam os argumentos passados ​​como varargs, são armazenados em uma matriz que é referida pelo nome dado a varargs. Nesse programa, o nome da matriz é valores. Observe também que o método é chamado com número diferente de argumentos, primeira chamada com quatro argumentos, depois três argumentos e depois com zero argumentos. Todas essas chamadas são tratadas pelo mesmo método que leva varargs.

Restrição com varargs

É possível ter outros parâmetros com o parâmetro varargs em um método, no entanto, nesse caso, o parâmetro varargs deve ser o último parâmetro declarado pelo método.

void displayValues(int a, int b, int  values) // OK
   void displayValues(int a, int b, int  values, int c) // compiler error

Outra restrição com varargs é que deve haver apenas um parâmetro varargs.

void displayValues(int a, int b, int  values, int  moreValues) // Compiler error

Sobrecarregando varargs Métodos

É possível sobrecarregar um método que aceita o parâmetro varargs. O método Varargs pode ser sobrecarregado por -

Os tipos de seu parâmetro vararg podem ser diferentes. Adicionando outros parâmetros. Exemplo de sobrecarga do método varargs

public class OverloadingVarargsExp {
 // Method which has string vararg parameter
 public void displayData(String ... values){
  System.out.println("Number of arguments passed " + values.length);
  for(String s : values){
   System.out.println(s + " ");
  }
 }

 // Method which has int vararg parameter
 public void displayData(int ... values){
  System.out.println("Number of arguments passed " + values.length);
  for(int i : values){
   System.out.println(i + " ");
  }
 }

 // Method with int vararg and one more string parameter
 public void displayData(String a, int ... values){
  System.out.println(" a " + a);
  System.out.println("Number of arguments passed " + values.length);
  for(int i : values){
   System.out.println(i + " ");
  }
 }

 public static void main(String[] args) {
  OverloadingVarargsExp vObj = new OverloadingVarargsExp();
  // four string args
  vObj.displayData("var", "args", "are", "passed");

  // two int args
  vObj.displayData(10, 20);

  // One String param and two int args
  vObj.displayData("Test", 20, 30);
 }
}
Output

Number of arguments passed 4
var 
args 
are 
passed 

Number of arguments passed 2
10 
20

 a Test
Number of arguments passed 2
20 
30 

Varargs e ambiguidade de sobrecarga

Em alguns casos, a chamada pode ser ambígua enquanto sobrecarregamos o método varargs. Vamos ver um exemplo

public class OverloadingVarargsExp {
 // Method which has string vararg parameter
 public void displayData(String ... values){
  System.out.println("Number of arguments passed " + values.length);
  for(String s : values){
   System.out.println(s + " ");
  }
 }

 // Method which has int vararg parameter
 public void displayData(int ... values){
  System.out.println("Number of arguments passed " + values.length);
  for(int i : values){
   System.out.println(i + " ");
  }
 }

 public static void main(String[] args) {
  OverloadingVarargsExp vObj = new OverloadingVarargsExp();
  // four string args
  vObj.displayData("var", "args", "are", "passed");

  // two int args
  vObj.displayData(10, 20);

  // This call is ambiguous
  vObj.displayData();
 }
}

Neste programa, quando fazemos uma chamada para o método displayData () sem nenhum parâmetro, ele gera erro, porque o compilador não tem certeza se essa chamada de método é para displayData(String ... values)oudisplayData(int ... values)

Da mesma forma, se sobrecarregamos métodos em que um tem o varargmétodo de um tipo e outro método tem um parâmetro e varargparâmetro do mesmo tipo, também temos a ambiguidade - As Exp - displayData(int ... values)edisplayData(int a, int ... values)

Esses dois métodos sobrecarregados sempre terão ambiguidade.

SIW
fonte
15

Esta é a maneira Java de passar varargs (argumentos de número variável).

Se você conhece C, isso é semelhante à ...sintaxe usada na printffunção:

int printf(const char * format, ...);

mas de uma maneira segura: todo argumento deve estar em conformidade com o tipo especificado (na sua amostra, eles devem ser todos String).

Este é um exemplo simples de como você pode usar varargs :

class VarargSample {

   public static void PrintMultipleStrings(String... strings) {
      for( String s : strings ) {
          System.out.println(s);
      }
   }

   public static void main(String[] args) {
      PrintMultipleStrings("Hello", "world");
   }
}

O ...argumento é na verdade uma matriz, então você pode passar um String[]como parâmetro.

lornova
fonte
11

Indiscutivelmente, é um exemplo de açúcar sintático, já que é implementado como uma matriz de qualquer maneira (o que não significa que seja inútil) - eu prefiro passar uma matriz para mantê-la clara e também declarar métodos com matrizes de determinado tipo. Antes, uma opinião do que uma resposta.

MichaelS
fonte
5

Também para esclarecer algumas coisas, é importante saber que os parâmetros var-arg são limitados a um e você não pode ter vários parâmetros de var-art. Por exemplo, isso é ilegal:

public void myMethod(String... strings, int ... ints){
// method body
}
Mr.Q
fonte
4

Pense nisso como a palavra-chave paramsem C #, se você vier desse plano de fundo :)

Ε Г И І И О
fonte
Eu sou um programador de C #.
Programador Orientado a Dinheiro
2

Uma maneira realmente comum de ver um exemplo claro do uso dos três pontos está presente em um dos métodos mais famosos do Android AsyncTask (que hoje não é muito usado por causa do RXJAVA, sem mencionar os componentes da arquitetura do Google), você pode encontrar milhares de exemplos pesquisando esse termo, e a melhor maneira de entender e nunca mais esquecer o significado dos três pontos é que eles expressam uma ... dúvida ... como no idioma comum. Ou seja, não está claro o número de parâmetros que precisam ser passados, pode ser 0, pode ser 1, pode ser mais (uma matriz) ...

trocchietto
fonte
1

String... é o mesmo que String[]

import java.lang.*;

public class MyClassTest {

    //public static void main(String... args) { 

    public static void main(String[] args) {
        for(String str: args) {
            System.out.println(str);
        }
    }
}
Uddhav Gautam
fonte
1
Se String...é o mesmo que String[], você não poderia simplesmente dizer isso?
Scott Hunter
8
Tecnicamente, isso não é verdade porque String[]requer um argumento (pelo menos uma matriz vazia) String...e não (veja a resposta acima).
Aurel
0

Adicionando outras respostas bem escritas, uma vantagem varagrsque achei útil é que, quando chamo um método com matriz como um tipo de parâmetro, elimina a necessidade de criar uma matriz; adicione elementos e depois envie-o. Em vez disso, posso simplesmente chamar o método com quantos valores quiser; de zero a muitos.

PhantomReference
fonte
0
  • Significa zero ou vários parâmetros do mesmo tipo de dados.
  • Deve ser o último parâmetro do construtor ou função.
  • Podemos ter apenas um parâmetro deste tipo no respectivo construtor ou função.

Exemplo 1:

public class quest1 {

    public quest1(String... mynum) {
        System.out.println("yee haa");
    }

    public static void main(String[] args) {
        quest1 q=new quest1();

        quest1 q1=new quest1("hello");

    }
}

Exemplo 2:

public class quest1 {

    public quest1(int... at) {
        System.out.println("yee haa");
    }

    public quest1(String... at) {
        System.out.println("yee haa");
    }

    public static void main(String[] args) {
        quest1 q=new quest1("value");

        quest1 q1=new quest1(1);

    }

    public void name(String ... s) {

    }
}

resultado:

yee haa

yee haa

Shubham Jain
fonte
-1

Sintaxe: (ponto triplo ...) -> significa que podemos adicionar zero ou mais objetos a passar em argumentos ou passar uma matriz do tipo objeto.

public static void main(String[] args){}
public static void main(String... args){}

Definição: 1) O argumento Objeto ... é apenas uma referência a uma matriz de Objetos.

2) ('String []' ou String ...) É capaz de lidar com qualquer número de objetos de string. Internamente, ele usa uma matriz de objeto do tipo de referência.

i.e. Suppose we pass an Object array to the ... argument - will the resultant argument value be a two-dimensional array - because an Object[] is itself an Object:

3) Se você quiser chamar o método com um único argumento e ele for uma matriz, será necessário envolvê-lo explicitamente

another. method(new Object[]{array}); 
OR 
method((Object)array), which will auto-wrap.

Aplicação: É usado principalmente quando o número de argumentos é dinâmico (número de argumentos conhecidos em tempo de execução) e sobrescrevendo. Regra geral - No método, podemos passar qualquer tipo e qualquer número de argumentos. Não podemos adicionar argumentos de objeto (...) antes de argumentos específicos. ie

void m1(String ..., String s) this is a wrong approach give syntax error.
void m1(String s, String ...); This is a right approach. Must always give last order prefernces.   
Vishal Sheth
fonte