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 設計者の場合は、利点がはっきりしている場合にだけ、慎重に使用するべきです。一般的に、可変長引数メソッドはオーバーロードしないようにしてください。オーバーロードすると、プログラマにとっては、どのオーバーロードが呼び出されたのかわかりにくくなるからです。