以下のようなメソッドを書こうとすると
public void someStuff(Object ... args, String a )
このエラーが発生します
メソッドsomeStuffの可変引数タイプObjectは、最後のパラメーターである必要があります。
可変引数型が最後であるという要件を完全には理解していません。任意の入力が役立ちます。
以下のようなメソッドを書こうとすると
public void someStuff(Object ... args, String a )
このエラーが発生します
メソッドsomeStuffの可変引数タイプObjectは、最後のパラメーターである必要があります。
可変引数型が最後であるという要件を完全には理解していません。任意の入力が役立ちます。
コンパイラがどの引数がどれであるかを判断できるように、変数引数は最後である必要があります。
たとえば、合格したとしましょう
「テスト」、「テスト」、「テスト」、「テスト」
あなたの機能に
public void someStuff(Object ... args, String a)
args変数に3つまたは4つの文字列を含める場合、Javaは機能しません。これを書いている時点では明らかかもしれませんが、あいまいです。
ただし、その逆の場合
public void someStuff(String a, Object ... args)
Javaコンパイラは、最初の文字列を確認し、それを「a」に貼り付けてから、残りの文字列を安全にargsに入れることができ、変数にあいまいさがないことを認識します。
これはCの規則に従います。次に、C規則は、スタックに引数を渡すCPUアーキテクチャに基づいています。最初の非vararg引数は、スタックフレーム内の固定オフセットで終了します。vararg引数を最初に配置できる場合、次の引数のスタックオフセットは、渡したvarargパラメーターの数によって異なります。これは、それらにアクセスするために必要なコードの量を非常に複雑にします。
あなたの例では、String a
最初に、後続のvararg引数の数に関係なく、概念的にオフセット0にあります。しかしString a
最後に、それはオフセットargs.size * 4
0、4、8、12などになる可能性があります-必要なたびに計算する必要がありますString a
。
それは言語を不必要に複雑にするからです。他の構文も許可した場合を想像してみてください。
public void someStuff(String a, Object ... args, String b)
{
}
あるいは:
public void someStuff(String a, Object ... args, int b, Object ... args2)
{
}
この2番目の構文は、文字列、Object型の任意の数の引数、整数、さらに多くのオブジェクトを意味します。確かに、そのようなことを受け入れることができる言語を設計することはできますが、args2に少なくとも1つの要素が含まれている必要があるが、argsは空である可能性があることも指定したい場合はどうでしょうか。なぜ私たちもそれができないのですか?あなたはそのような言語をデザインすることができます。
要約すると、ルールをどの程度複雑にしますか?この場合、彼らはニーズを満たすシンプルなオプションを選択しました。
文字列もオブジェクトのインスタンスであるため、varargsを使用している場合は、コンパイラが実際にargsと文字列を決定できないため、vararg配列を最後のパラメータにする必要があります。メソッド呼び出しは、メソッド名のタプルとパラメーターであるオブジェクトのリストと考えてください。このような2つの方法がある場合:
public void someStuff(Object ... args, String a )
public void someStuff(String a, String b)
コンパイラは、someStuff( "Hello"、 "Hello")に選択するメソッドを決定できませんでした。文字列aを最初の引数として指定すると、someStuff(String、String)がsomeStuff(String、Object)よりも具体的であると判断できます。
var argsを使用するメソッドがどのように使用されるかを考えると、他の形式ではあいまいさが生じる可能性があります。varargsを最後に持つことで、機能の利点を減らす可能性のあるあいまいさを解決するための追加の構文を必要とせずに、起こりうるあいまいさを防ぎます。
次のメソッド宣言について考えてみます。
public void varargsAreCool(String surname, String firstname,
String... nicknames) {
// some cool varargs logic
}
ニックネームがないのはvarargsAreCool("John", "Smith")
明らかです。John Smith
このように使用するとvarargsAreCool("Andrew", "Jones", "The Drew", "Jonesy")
。
ここで、次の無効なメソッド宣言について考えてみます。
public void varargsAreCool(String surname, String... nicknames,
String firstname) {
// some cool varargs logic
}
ジョンのニックネームまたは彼の名前のようvarargsAreCool("John", "Smith")
に使用されるとき?Smith
彼の名前の場合、ニックネームがないことをどのように示しますか?これを行うには、おそらくこのような方法を使用する必要がありますが、varargsAreCool("John", new String[]{}, "Smith")
これは不格好で、機能の目的をいくらか無効にします。
このように使用するとvarargsAreCool("Andrew", "The Drew", "Jonesy", "Jones")
、The Drew, Jonesy and Jones
すべてのニックネームがあり、名前が欠落していますか?この場合も、このあいまいさは解決できますが、追加の構文が不格好になります。