Java, 3 точки в параметрах

678

Что означают три точки в следующем методе?

public void myMethod(String... strings){
    // method body
}
Теги:
variadic-functions

9 ответов

872
Лучший ответ

Это означает, что в качестве аргумента (ов) для этого метода могут быть переданы ноль или более объектов String (или их массив).

Смотрите раздел "Произвольное количество аргументов" здесь: http://java.sun.com/docs/books/tutorial/java/javaOO/arguments.html#varargs

В вашем примере вы можете назвать это следующим образом:

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

Важное примечание: Аргумент (ы), переданный таким образом, всегда является массивом, даже если есть только один. Убедитесь, что вы относитесь к этому методу в теле метода.

Важное примечание 2: Аргумент, который получает ..., должен быть последним в сигнатуре метода. Итак, myMethod(int i, String... strings) в порядке, но myMethod(String... strings, int i) не в порядке.

Спасибо Вашу за разъяснения в его комментарии.

  • 102
    Вы ошибаетесь, в этом «один или несколько», с помощью varargs мы можем указать 0 или более, и это всегда должно быть последним параметром в методе. Метод x (String ... params) может быть вызван как x (), или метод y (String pram, String ... params) может быть вызван как y ("1")
  • 2
    Я бы хотел, чтобы это тоже сработало. myMethod ("one", "two", "three", new String [] {"a", "b", "c" "});
Показать ещё 6 комментариев
107

Эта функция называется varargs, и это функция, введенная в Java 5. Это означает, что функция может принимать несколько аргументов String

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

Затем вы можете использовать String var как массив:

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]
    }
}

Этот ответ сильно заимствован из кисвы и Лоренцо... а также из комментария Графана.

  • 13
    Когда код попадает в байт - код, это массив. Все остальное синтаксис поддерживается только компилятором.
  • 0
    Этот ответ в значительной степени заимствует у Кишвы и Лоренцо, если я правильно читаю правки.
Показать ещё 3 комментария
12

Это способ Java для передачи varargs (аргументы с переменным числом).

Если вы знакомы с C, это похоже на синтаксис ..., который использовал функцию printf:

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

но безопасным типом: каждый аргумент должен соответствовать указанному типу (в вашем примере они должны быть все String).

Это простой пример того, как вы можете использовать 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");
   }
}

Аргумент ... на самом деле является массивом, поэтому вы можете передать String[] в качестве параметра.

10

Это Varargs :)

Короткие аргументы varargs для аргументов переменной длины - это функция, которая позволяет методу принимать переменное количество аргументов (ноль или более). С помощью varargs стало проще создавать методы, которые должны принимать переменное количество аргументов. Функция переменной аргумента добавлена в Java 5.

Синтаксис varargs

Параметр vararg разделяется на три эллипса (три точки) после типа данных, его общий вид

return_type method_name(data_type ... variableName){
}  

Потребность в варгарах

До появления Java 5 в случае необходимости переменного количества аргументов было два способа справиться с этим

Если максимальное количество аргументов, метод может принимать, был мал и известен, то могут быть созданы перегруженные версии метода. Если максимальное количество аргументов, которые мог бы принять метод, было большим или/и неизвестным, то подход заключался в том, чтобы поместить эти аргументы в массив и передать их методу, который принимает массив в качестве параметра. Эти два подхода были подвержены ошибкам - каждый раз создавали массив параметров и их трудно поддерживать, поскольку добавление нового аргумента может привести к написанию нового перегруженного метода.

Преимущества варгаров

Предлагает гораздо более простой вариант. Меньше кода, так как нет необходимости писать перегруженные методы.

Пример 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

Из программы видно, что длина используется здесь, чтобы найти количество аргументов, переданных методу. Это возможно, потому что varargs неявно передается как массив. Независимо от того, какие аргументы передаются, поскольку varargs хранятся в массиве, который называется именем, заданным для varargs. В этом имени массива программы находятся значения. Также обратите внимание, что метод вызывается с различным количеством аргументов, первым вызовом с четырьмя аргументами, затем тремя аргументами, а затем с нулевыми аргументами. Все эти вызовы обрабатываются тем же методом, что и varargs.

Ограничение с помощью varargs

В методе возможны другие параметры с параметром varargs, однако в этом случае параметр varargs должен быть последним параметром, объявленным методом.

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

Другое ограничение с varargs состоит в том, что должен быть только один параметр varargs.

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

Перегрузка методов varargs

Можно перегрузить метод, который принимает параметр varargs. Метод Varargs может быть перегружен -

Типы его параметра vararg могут быть разными. Добавляя другие параметры. Пример метода перегрузки 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 и перегрузка неоднозначности

В некоторых случаях вызов может быть неоднозначным, когда мы перегружаем метод 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 + " ");
  }
 }

 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();
 }
}

В этой программе, когда мы вызываем метод displayData() без какого-либо параметра, он выдает ошибку, потому что компилятор не уверен, является ли этот вызов метода для displayData(String... values) или displayData(int... values)

То же самое, если у нас есть перегруженные методы, когда у vararg метод vararg одного типа, а другой метод имеет один параметр и параметр vararg того же типа, то также мы имеем двусмысленность - как Exp - displayData(int... values) и displayData(int a, int... values)

Эти два перегруженных метода всегда будут иметь двусмысленность.

10

Возможно, это пример синтаксического сахара, поскольку он реализован как массив в любом случае (это не значит, что это бесполезно). Я предпочитаю передавать массив, чтобы он был ясен, а также объявлять методы с массивами заданного типа, Скорее, мнение, чем ответ.

4

Также, чтобы пролить некоторый свет, важно знать, что параметры var-arg ограничены одним, и вы не можете иметь несколько параметров var-art. Например, это нелогично:

public void myMethod(String... strings, int ... ints){
// method body
}
3

Подумайте об этом как ключевое слово params в С#, если вы исходите из этого фона:)

  • 0
    Я программист на C #.
2

String... совпадает с 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);

        }
        }
        }
  • 1
    Если String... такой же, как String[] , не могли бы вы просто сказать это?
  • 0
    Ваши слова лаконичны и понятны. Благодарю.
Показать ещё 1 комментарий
1

На самом деле распространенный способ увидеть ясный пример использования трех точек, присутствующих в одном из самых известных методов в android AsyncTask (что сегодня не слишком много используется из-за RXJAVA, не говоря уже о компонентах Google Architecture), вы можете найти тысячи примеров, ищущих этот термин, и лучший способ понять и никогда не забывать о значении три точки - это то, что они выражают... сомнение... точно так же, как на общем языке. А именно, неясно, сколько параметров должно быть передано, может быть 0, может быть 1 может быть больше (массив)...

Ещё вопросы

Сообщество Overcoder
Наверх
Меню