可変引数メソッドって何者か(「いくつ来るかわからない」を受け止める仕組み)
可変引数(varargs)は、同じ型の引数を 0 個以上まとめて受け取るための仕組みです。 メソッド定義で int... nums のように書くと、呼び出し側は好きな数だけ値を渡せます。
public static int sum(int... nums) {
int total = 0;
for (int n : nums) {
total += n;
}
return total;
}
Java呼び出し側はこう使えます。
sum(); // 0個
sum(10); // 1個
sum(10, 20, 30); // 3個
Java「引数の数が呼び出し側によって変わる」場面で、可変引数は非常に便利です。 ユーティリティメソッド(共通処理)でよく使われる理由は、柔軟性が高く、呼び出し側の負担が少ないからです。
可変引数の正体は「配列」である
メソッド内部では配列として扱われる
可変引数は、内部では普通の配列として扱われます。
public static void debug(String... messages) {
System.out.println("件数: " + messages.length);
for (String msg : messages) {
System.out.println("DEBUG: " + msg);
}
}
Java呼び出し側はこう書けます。
debug("start");
debug("load", "connect", "finish");
Java内部では messages が String[] として扱われるので、 length で個数を調べたり、拡張 for 文で回したりできます。
配列引数との違いを理解する
配列を渡すメソッドと比較してみます。
public static int sumArray(int[] nums) { ... }
Java呼び出し側は配列を作る必要があります。
sumArray(new int[]{10, 20, 30});
Java可変引数なら、配列を作らずにそのまま渡せます。
sum(10, 20, 30);
Java呼び出し側の書き心地が圧倒的に軽いのが可変引数の強みです。
可変引数のルールと注意点(ここは重要)
可変引数は「最後の引数」にしか書けない
次のような定義は OK です。
public static void log(String level, String... messages) { ... }
Javaしかし、次のような定義は NG です。
// コンパイルエラー
public static void bad(String... messages, String suffix) { ... }
Java理由は、どこまでが可変引数で、どこからが次の引数なのか判別できないためです。 可変引数は必ず最後に置く、というルールを覚えておきましょう。
オーバーロードと組み合わせるときは慎重に
可変引数は柔軟すぎるため、オーバーロードと組み合わせると曖昧さが生まれることがあります。
public void print(int... nums) { ... }
public void print(int n) { ... }
Java呼び出し側が print(5) と書いたとき、どちらが呼ばれるか分かりづらくなります。 可変引数を使うときは、オーバーロードを増やしすぎないことが大事です。
汎用ユーティリティでの可変引数の使いどころ
ログ出力ユーティリティ
ログは「複数のメッセージをまとめて出したい」場面が多いので、可変引数がよく使われます。
public static void info(String... messages) {
for (String msg : messages) {
System.out.println("[INFO] " + msg);
}
}
Java呼び出し側はこう書けます。
info("start", "loading", "done");
Java「複数メッセージをまとめてログに出す」という意図が、呼び出し側のコードから自然に伝わります。
数値処理ユーティリティ
例えば「最大値を求める」メソッド。
public static int max(int... nums) {
int result = Integer.MIN_VALUE;
for (int n : nums) {
if (n > result) result = n;
}
return result;
}
Java呼び出し側はこう書けます。
max(3, 10, 7, 2);
Java「何個来るか分からないけど全部比較したい」という処理にぴったりです。
文字列結合ユーティリティ
public static String join(String sep, String... parts) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < parts.length; i++) {
sb.append(parts[i]);
if (i < parts.length - 1) sb.append(sep);
}
return sb.toString();
}
Java呼び出し側はこう書けます。
String s = join(", ", "A", "B", "C");
System.out.println(s); // A, B, C
Java「区切り文字付きで連結したい」という処理を、可変引数でシンプルに書けます。
可変引数を使うときの設計ポイント(深掘り)
「本当に可変である必要があるか」を考える
可変引数は便利ですが、乱用するとメソッドの意図がぼやけます。
例えば「必ず3つの値が必要な処理」なのに可変引数にしてしまうと、
calc(a, b); // 足りない
calc(a, b, c, d); // 多すぎる
Javaといった誤用がコンパイル時に検出できなくなります。
可変であること自体が仕様の一部になっているか? ここを自問してから使うと、設計が安定します。
呼び出し側の負担を減らすために使う
可変引数の最大のメリットは、呼び出し側のコードが軽くなることです。
配列を作らなくていい 値をそのまま並べて渡せる 読みやすい
ユーティリティメソッドでは「呼び出し側の負担を減らす」ことが重要なので、 可変引数はその目的に非常に合っています。
まとめと練習
可変引数(...)は、同じ型の引数を 0 個以上受け取るための柔軟な仕組みで、 内部では配列として扱われ、ユーティリティメソッドで特に威力を発揮します。
練習として次の2つを自分で書いてみると理解が深まります。
練習1:任意個の整数の平均値を返すメソッド
double avg(int... nums)
Java練習2:任意個の文字列を「|」で結合するメソッド
String joinWithBar(String... parts)
Java「可変であることが仕様の一部になっているか」「呼び出し側が楽になるか」を意識しながら書くと、 可変引数メソッドを“設計できる”感覚が身につきます。

