web-dev-qa-db-ja.com

Java、パラメータに3ドット

次のメソッドの3つのドットはどういう意味ですか?

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

つまり、そのメソッドの引数として、0個以上の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"});

重要な注意: この方法で渡された引数は、たとえ1つだけであっても常に配列です。メソッド本体でそのように扱うようにしてください。

重要な注意2: ...を取得する引数は、メソッドシグネチャの最後でなければなりません。そのため、myMethod(int i, String... strings)は問題ありませんが、myMethod(String... strings, int i)は問題ありません。

彼のコメントの明確化についてVashに感謝します。

877
kiswa

この機能は 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]
    }
}

この答えは、キスワやロレンツォの、そしてグラパインのコメントからも深く借りています。

108
Cristian

これは、 varargs (可変数引数)を渡すためのJavaの方法です。

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[]をパラメータとして渡すことができます。

12
lornova

それは可変引数です :)

可変長引数の可変長引数は、メソッドが可変数(ゼロ以上)の引数を受け入れることを可能にする機能です。可変引数を使用すると、可変数の引数を取る必要があるメソッドを作成するのが簡単になりました。可変引数の機能はJava 5で追加されました。

可変引数の構文

可変長は、データ型の後に3つの省略記号(3つのドット)で区切られています。一般的な形式は次のとおりです。

return_type method_name(data_type ... variableName){
}  

可変引数の必要性

Java 5より前のバージョンでは、可変数の引数が必要な場合に対処する方法が2つありました。

1つのメソッドで使用できる引数の最大数が少なく、既知である場合は、メソッドのオーバーロードバージョンを作成できます。メソッドが取ることができる引数の最大数が大きかったり未知数だったりするならば、アプローチはそれらの引数を配列に入れ、それらを引数として配列を取るメソッドに渡すことでした。新しい引数を追加すると、新しいオーバーロードされたメソッドが作成される可能性があるため、これら2つのアプローチはエラーが発生しやすく、毎回パラメータの配列を作成して維持するのは困難でした。

可変引数の利点

もっと簡単なオプションを提供します。オーバーロードされたメソッドを書く必要がないのでコードが少なくなります。

可変引数の例

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に与えられた名前で参照される配列に格納されます。このプログラムでは、配列名は値です。また、methodは異なる数の引数で呼び出されることに注意してください。最初に4つの引数、次に3つの引数、次にゼロの引数で呼び出します。これらの呼び出しはすべて、引数をとるのと同じメソッドによって処理されます。

可変引数による制限

メソッド内にvarargsパラメータを持つ他のパラメータを含めることは可能ですが、その場合は、varargsパラメータをメソッドによって宣言された最後のパラメータにする必要があります。

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

Varargsのもう1つの制限は、varargsパラメータは1つだけでなければならないということです。

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

可変引数メソッドのオーバーロード

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 + " ");
  }
 }

 // 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メソッドをオーバーロードしている間に呼び出しがあいまいになることがあります。例を見てみましょう

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パラメータを持つメソッドがオーバーロードされている場合も同様に、あいまいさがあります。 - Exp - displayData(int ... values)displayData(int a, int ... values)

これら2つのオーバーロードされたメソッドは常にあいまいさがあります。

12
SIW

それはとにかく配列として実装されているので(おそらく無用ではないので)、それは構文糖の例です。答えよりもむしろ意見です。

11
MichaelS

また、いくつかの光を当てるために、var-argパラメータが1つに制限されていることを知っておくことは重要です、そしてあなたはいくつかのvar-artパラメータを持つことができません。たとえば、これは不公平です。

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

あなたがその背景から来ているのであれば、C#のキーワードparamsと考えてください。

4

それがAndroidで最も有名な方法の1つに存在する3つのドットの使用の明確な例を見るための本当に一般的な方法 AsyncTask (今日はグーグルは言うまでもなくRXJAVAのためにあまり使われないこの3つの点の意味を理解し、もう忘れないようにするための最善の方法は、それらが共通の言語のように...疑い...を表現することです。つまり、渡す必要があるパラメータの数が明確ではなく、0、1、それ以上(配列)などの可能性があります。

1
trocchietto

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
Uddhav Gautam