MessageFormatクラスを使用してメッセージをフォーマットする例を示します。
Object[] arguments = {
new Integer(7),
new Date(),
"a disturbance in the Force"
};
String result = MessageFormat.format(
"At {1,time} on {1,date}, there was {2} on planet "
+ "{0,number,integer}.", arguments);
複数の引数を配列で渡す必要があることは変わりありませんが、その処理が可変長引数機能が自動化され、ユーザーからは隠されます。 さらに、既存のAPIとの上位互換性があります。 そのため、たとえばMessageFormat.formatメソッドに、次の宣言が追加されました。
public static String format(String pattern,
Object... arguments);
最後の引数の型の後ろに続く3つのピリオドは、最後の引数が配列、つまり一連の引数として渡されることを示しています。 可変長引数は、最後の引数の位置でだけ使用できます。 MessageFormat.formatに可変長引数宣言が追加されたことで、上記の呼出しは、次のように短くわかりやすい呼出しに置き換えることができます。
String result = MessageFormat.format(
"At {1,time} on {1,date}, there was {2} on planet "
+ "{0,number,integer}.",
7, new Date(), "a disturbance in the Force");
Autoboxingと可変長引数との間には強いシナジーがあります。リフレクションを使用する次のプログラムで示します。
// Simple test framework
public class Test {
public static void main(String[] args) {
int passed = 0;
int failed = 0;
for (String className : args) {
try {
Class c = Class.forName(className);
c.getMethod("test").invoke(c.newInstance());
passed++;
} catch (Exception ex) {
System.out.printf("%s failed: %s%n", className, ex);
failed++;
}
}
System.out.printf("passed=%d; failed=%d%n", passed, failed);
}
}
この短いプログラムは、たとえ小さくても、完全なテスト・フレームワークです。 コマンド行でクラス名のリストを取ります。 クラス名ごとにパラメータなしコンストラクタでクラスをインスタンス化し、testというパラメータなしメソッドを呼び出します。 インスタンス化または呼出しが例外をスローした場合、testは失敗したと見なされます。 プログラムは問題を出力してから、test結果のサマリーを出力します。 リフレクション・ベースのインスタンス化および呼出しで、明示的な配列作成が必要なくなりました。getMethodメソッドとinvokeメソッドが可変長引数リストを受け入れるためです。 またこのプログラムは、可変長引数を利用する新しいprintf機能を使用しています。 可変長引数を使用しない場合と比べて、プログラムは非常に読みやすくなります。
クライアントの場合は、 APIが可変長引数を提供しているときは、必ず利用するべきです。 コアAPIでの重要な使用例は、リフレクション、メッセージ・フォーマット、新しいprintf機能などです。 API設計者の場合は、利点がはっきりしている場合にだけ、慎重に使用するべきです。 一般的に、可変長引数メソッドはオーバーロードしないようにしてください。オーバーロードすると、プログラマにとっては、どのオーバーロードが呼び出されたのかわかりにくくなるからです。