メソッド宣言と可変長引数を理解する

可変長引数は、呼出し時に0個以上の値を並べて渡せる宣言です。メソッド本体では配列として扱います。メソッド宣言の基本に加え、配列を直接渡す場合とnull、オーバーロードとの関係を学びます。

この単元で学ぶこと

  • 可変長引数を配列として説明する
  • 宣言位置と呼出しの合法性を判定する
  • 配列・null・オーバーロードの結果を追う

本文解説

宣言と本体 static int count(int... xs){return xs.length;}のint... xsが可変長引数です。本体ではint[]と同じようにlengthや添字を使えます。count(2,4,6)なら三要素の配列として渡されるので3です。戻り値の型はintで、...は戻り値ではなく引数側に書きます。

0個でも呼べる count()は空のint配列を受け取り0を返します。count(7)は一要素なので1です。空配列とnullは別なので、引数を省略した場合にxsがnullになると考えないようにします。xs[0]を無条件に読む本体なら、0個の呼出しで範囲外例外になります。

配列をそのまま渡す int[] a={2,4};count(a)でも2です。可変長引数を配列型の仮引数として使えるためです。この場合はaが指す配列への参照値がそのまま渡され、本体でxs[0]を書き換えると元の配列にも見えます。毎回必ず配列を複製する仕組みではありません。

固定引数と組み合わせる static int sum(int base,int... xs){for(int x:xs)base+=x;return base;}ではbaseを一つ必ず渡し、その後は0個以上です。sum(10,1,2)は13、sum(10)は10。可変長引数は仮引数リストの最後に一つだけ宣言できます。int... xs,int lastの順は不正です。

配列型との同一性 static void f(int... xs)とstatic void f(int[] xs)は同じクラスへ同時宣言できません。可変長引数もシグネチャ上は配列型として扱われるからです。...の有無だけで二つの独立したメソッドを作ることはできません。

nullの渡し方 count((int[])null)はnull配列を受け取り、lengthの参照でNullPointerExceptionになります。int...には整数要素としてnullを一つ詰めることはできません。String...なら(String)nullを一要素として渡す場合と(String[])nullを配列として渡す場合を区別できます。

通常の引数を先に検討 f(int)とf(int...)があると、f(1)は固定引数のint版を選び、f()やf(1,2)は可変長版を選びます。配列を直接渡すf(new int[]{1})は配列型として可変長宣言へ適用できます。「可変長版は常に最後」と考えるだけでなく、固定個数の配列引数として適用できる段階も確認します。

実行確認 0個、一個、複数、配列直接、null配列を別々に試します。lengthと要素を表示し、引数を並べた場合の配列と直接渡した配列の変更先を比較します。不正な宣言順や同一シグネチャは実行できないため、コンパイル診断を確認して分類します。

図解

可変長引数の受取方
どの呼出しでも本体のxsは配列型だが、空・null・共有の違いがある。

重要ポイント

  • 可変長引数の本体での型は配列。
  • 0個の呼出しは空配列でありnullではない。
  • 可変長引数は最後に一つだけ宣言する。
  • 配列宣言と...宣言だけの違いではオーバーロードできない。

間違えやすい点

  • 可変長引数の要素数と固定引数の個数を混同しない。
  • 配列を直接渡しても必ず複製されると思わない。
  • null配列とnull要素を区別する。

用語解説

可変長引数
0個以上の引数をまとめて受け取れる末尾の配列型仮引数。
固定引数
個数と位置が決まった通常の仮引数。
空配列
要素数が0の配列オブジェクト。
配列直接指定
既存の配列参照を可変長引数の配列型へ渡す呼出し。

関連教材

参考資料

教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。

確認問題の出題・採点や学習履歴の保存にはログインが必要です。