可変長引数


これまでのリリースでは、任意の個数の値を取るメソッドでは、そのメソッドの呼出し前に、配列を作成してそれらの値を配列に入れる必要がありました。たとえば、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設計者の場合は、利点がはっきりしている場合にだけ、慎重に使用するべきです。一般的に、可変長引数メソッドはオーバーロードしないようにしてください。オーバーロードすると、プログラマにとっては、どのオーバーロードが呼び出されたのかわかりにくくなるからです。


Copyright © 1993, 2020, Oracle and/or its affiliates. All rights reserved.