可変引数が怖いです。私はそれらを何に使うのか分かりません。
さらに、必要なだけ多くの引数を渡すことは危険です。
それらを使用するのに適したコンテキストの例は何ですか?
Varargsは、usefulであり、不定数のオブジェクト。良い例の1つは String.format
です。フォーマット文字列は任意の数のパラメーターを受け入れることができるため、任意の数のオブジェクトを渡すメカニズムが必要です。
String.format("This is an integer: %d", myInt);
String.format("This is an integer: %d and a string: %s", myInt, myString);
目安は次のとおりです。
「入力としてTの配列(タイプTが何であれ)を必要とする任意のメソッド(またはコンストラクター)に可変引数を使用します。」
これにより、これらのメソッドの呼び出しが簡単になります(new T[]{...}
を実行する必要はありません)。
この引数が入力専用である場合(つまり、リストがメソッドによって変更されていない場合)、List<T>
引数を持つメソッドを含めるようにこのルールを拡張できます。
また、f(Object... args)
を使用することは控えます。これは、そのAPIが不明確なプログラミング方法に移行するためです。
例として、私はそれを DesignGridLayout で使用しました。1回の呼び出しで複数のJComponent
sを追加できます。
layout.row().grid(new JLabel("Label")).add(field1, field2, field3);
上記のコードでは、add()メソッドはadd(JComponent... components)
として定義されています。
最後に、そのようなメソッドの実装は、空の可変引数で呼び出される可能性があるという事実に注意する必要があります!少なくとも1つの引数を指定する場合は、次のようないトリックを使用する必要があります。
void f(T arg1, T... args) {...}
メソッドの実装は、引数リストにT... args
を含めるよりも簡単ではないため、このトリックは見苦しいと思います。
これが可変引数に関するポイントの明確化に役立つことを願っています。
デバッグの目的でログに出力するために、可変引数を頻繁に使用します。
私のアプリのほとんどすべてのクラスにdebugPrint()メソッドがあります:
private void debugPrint(Object... msg) {
for (Object item : msg) System.out.print(item);
System.out.println();
}
次に、クラスのメソッド内で、次のような呼び出しがあります。
debugPrint("for assignment ", hwId, ", student ", studentId, ", question ",
serialNo, ", the grade is ", grade);
コードが機能していることに満足したら、debugPrint()メソッドのコードをコメントアウトして、ログに不要な情報や不要な情報が多く含まれないようにしますが、debugPrint()の個々の呼び出しはコメントなしのままにしておきます。後でバグを見つけた場合、debugPrint()コードのコメントを外すだけで、debugPrint()へのすべての呼び出しが再アクティブ化されます。
もちろん、varargsを簡単に回避して、代わりに次の操作を実行できます。
private void debugPrint(String msg) {
System.out.println(msg);
}
debugPrint("for assignment " + hwId + ", student " + studentId + ", question "
+ serialNo + ", the grade is " + grade);
ただし、この場合、debugPrint()コードをコメントアウトすると、サーバーは、結果の文字列で何も実行されていなくても、debugPrint()の呼び出しごとにすべての変数を連結するという問題を解決する必要があります。しかし、可変引数を使用する場合、サーバーは、可変引数を必要としないことに気付く前に、それらを配列に入れるだけです。多くの時間が節約されます。
メソッドで渡される引数の数がわからない場合は、可変引数を使用できます。バックグラウンドで不特定の長さのパラメーターの配列を作成し、そのようなパラメーターは実行時に配列として扱うことができます。
異なる数のパラメーターを受け入れるためにオーバーロードされたメソッドがある場合、メソッドを異なる時間にオーバーロードする代わりに、単にvarargsコンセプトを使用できます。
また、パラメータのタイプが変わる場合、「オブジェクト...テスト」を使用するとコードが大幅に簡素化されます。
例えば:
public int calculate(int...list) {
int sum = 0;
for (int item : list) {
sum += item;
}
return sum;
}
ここでは、間接的にint型(リスト)の配列がパラメーターとして渡され、コード内で配列として扱われます。
よりよく理解するには、このリンクをたどってください(この概念を明確に理解するのに大いに役立ちました): http://www.javadb.com/using-varargs-in-Java
追伸:私もそれを知らなかったとき、可変引数を使うことを恐れていました。しかし、今は慣れています。言われているように、「私たちは既知のものに固執し、未知のものを恐れている」ので、できるだけそれを使用してください。あなたもそれを好きになります:)
Varargsは、Javaバージョン1.5で追加された機能です。
これを使用する理由
これはどのように機能しますか?
指定された引数で配列を作成し、配列をメソッドに渡します。
例:
public class Solution {
public static void main(String[] args) {
add(5,7);
add(5,7,9);
}
public static void add(int... s){
System.out.println(s.length);
int sum=0;
for(int num:s)
sum=sum+num;
System.out.println("sum is "+sum );
}
}
出力:
2
合計は12
3
合計は21です
私も可変引数に関連した恐怖を持っています:
呼び出し元が明示的な配列を(複数のパラメーターではなく)メソッドに渡すと、その配列への共有参照を受け取ります。
この配列を内部に保存する必要がある場合は、最初に複製して、呼び出し元が後で変更できないようにすることができます。
Object[] args = new Object[] { 1, 2, 3} ;
varArgMethod(args); // not varArgMethod(1,2,3);
args[2] = "something else"; // this could have unexpected side-effects
これは、後で状態が変わる可能性のあるオブジェクトの種類を渡すことと実際には違いはありませんが、配列は通常(配列の代わりに複数の引数を持つ呼び出しの場合)、安全にできる内部的にコンパイラによって作成された新しいものです使用、これは確かに予期しない動作です。
ある種のフィルターオブジェクトを取得できるコンストラクターには、可変引数を頻繁に使用します。たとえば、Hadoopに基づいたシステムの大部分は、JSONへのアイテムのシリアル化と非シリアル化を処理し、それぞれがコンテンツのアイテムを取得して変更して返すか、nullを返す多くのプロセッサを適用するマッパーに基づいています拒否する。
Var-ArgsのJava docでは、var argsの使用法は非常に明確です。
http://docs.Oracle.com/javase/1.5.0/docs/guide/language/varargs.html
それは言う使用法について:
「それで、いつ可変引数を使用する必要がありますか?クライアントとして、APIが提供するときはいつでもそれらを利用する必要があります。一般的に言えば、可変引数メソッドをオーバーロードしないでください。そうしないと、プログラマーがどのオーバーロードが呼び出されるかを判断するのが困難になります。