可変長引数


これまでのリリースでは、任意の個数の値を取るメソッドでは、そのメソッドの呼出し前に、配列を作成してそれらの値を配列に入れる必要がありました。 たとえば、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, 2025, Oracle and/or its affiliates. All rights reserved.