第 11 章:可变参数与命令行参数
学习目标
- 掌握可变参数(varargs)的用法
- 理解可变参数的底层实现
- 学会解析 main 方法的命令行参数
一、什么是可变参数?
可变参数允许方法接受任意数量的同类型参数。
java
public static int sum(int... numbers) { // ① int... 表示可变参数
int total = 0;
for (int n : numbers) {
total += n;
}
return total;
}
// 可以传任意个 int
sum(1, 2); // 3
sum(1, 2, 3, 4, 5); // 15
sum(); // 0(零个参数)
sum(new int[]{1, 2}); // 3(传数组也行)二、可变参数的本质
可变参数底层就是数组:
java
// 这两种写法完全等价
public static int sum(int... numbers) { ... }
public static int sum(int[] numbers) { ... } // 等价三、可变参数的三条规则
3.1 只能有一个可变参数
java
// ❌ 编译报错
public void test(int... nums, String... strs) { }
// ✅ 合法
public void test(int... nums) { }3.2 必须放在参数列表最后
java
// ❌ 编译报错
public void test(String... strs, int count) { }
// ✅ 合法
public void test(int count, String... strs) { }3.3 调用时少传一个数组
java
// ✅ 可以直接传多个值
sum(1, 2, 3, 4, 5);
// ✅ 也可以传数组
sum(new int[]{1, 2, 3});四、可变参数的典型应用
4.1 字符串拼接
java
public static String concat(String separator, String... parts) {
return String.join(separator, parts);
}
concat("-", "2024", "08", "12"); // "2024-08-12"
concat("/", "a", "b", "c"); // "a/b/c"4.2 日志方法
java
public static void log(String format, Object... args) {
System.out.println(String.format(format, args));
}
log("用户 %s 登录失败,错误码 %d", "张三", 401);
// 输出:用户 张三 登录失败,错误码 4014.3 断言 / 校验
java
public static void requireNonNull(Object... args) {
for (int i = 0; i < args.length; i++) {
if (args[i] == null) {
throw new IllegalArgumentException("第 " + i + " 个参数为 null");
}
}
}
requireNonNull("a", "b", "c", null, "e"); // 抛异常五、可变参数 vs 数组参数
| 维度 | 可变参数 int... | 数组参数 int[] |
|---|---|---|
| 调用方式 | sum(1,2,3) | sum(new int[]{1,2,3}) |
| 空参数 | sum() 合法 | 必须传数组 |
| 重载冲突 | 可能冲突 | 不冲突 |
java
// ❌ 可变参数和数组不能重载
public void test(int... nums) { }
public void test(int[] nums) { } // 编译报错:与方法签名相同六、main 方法的命令行参数
java
public static void main(String[] args) {
// args 是 String[],接收命令行参数
}bash
# 运行 java MyApp arg1 arg2 arg3
# args = ["arg1", "arg2", "arg3"]java
public class ArgsDemo {
public static void main(String[] args) {
System.out.println("参数个数: " + args.length);
for (int i = 0; i < args.length; i++) {
System.out.println("args[" + i + "] = " + args[i]);
}
}
}bash
$ java ArgsDemo hello world 123
参数个数: 3
args[0] = hello
args[1] = world
args[2] = 123IDEA 配置参数:Run → Edit Configurations → Program arguments
七、完整代码示例
java
/**
* 可变参数与命令行参数示例
*
* 配套文档:第 11 章 可变参数与命令行参数
* 运行方式:java VarargsDemo a b c
*/
public class VarargsDemo {
// 可变参数求和
public static int sum(int... numbers) {
int total = 0;
for (int n : numbers) {
total += n;
}
return total;
}
// 字符串拼接
public static String join(String separator, String... parts) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < parts.length; i++) {
if (i > 0) sb.append(separator);
sb.append(parts[i]);
}
return sb.toString();
}
// 格式化日志
public static void log(String format, Object... args) {
System.out.println("[LOG] " + String.format(format, args));
}
// 校验非空
public static void checkNotNull(Object... args) {
for (int i = 0; i < args.length; i++) {
if (args[i] == null) {
throw new IllegalArgumentException(
"第 " + i + " 个参数不能为 null"
);
}
}
}
public static void main(String[] args) {
// 1. 可变参数
System.out.println("=== 可变参数求和 ===");
System.out.println("sum(1, 2) = " + sum(1, 2));
System.out.println("sum(1, 2, 3, 4, 5) = " + sum(1, 2, 3, 4, 5));
System.out.println("sum() = " + sum());
// 2. 字符串拼接
System.out.println("\n=== 字符串拼接 ===");
System.out.println(join("-", "2024", "08", "12"));
System.out.println(join("/", "a", "b", "c"));
// 3. 格式化日志
System.out.println("\n=== 格式化日志 ===");
log("用户 %s 登录 %s", "张三", "成功");
log("订单 %d 状态: %s", 12345, "已支付");
// 4. 命令行参数
System.out.println("\n=== 命令行参数 ===");
System.out.println("参数个数: " + args.length);
for (int i = 0; i < args.length; i++) {
System.out.println("args[" + i + "] = " + args[i]);
}
}
}八、本章小结
| 要点 | 关键 |
|---|---|
| 可变参数语法 | 类型... 名字 |
| 本质 | 编译为数组 |
| 规则 | 只有一个、必须在最后、可传数组 |
| main 参数 | String[] args 接收命令行参数 |
| 典型应用 | 求和、字符串拼接、格式化日志 |
动手练习
练习 1:基础题
写一个 max 方法的可变参数版本:
java
public static int max(int... numbers)
// max(1, 5, 3, 9, 2) = 9
// max() = Integer.MIN_VALUE(或者抛异常)练习 2:进阶题
写一个工具方法,判断所有参数是否都满足某个条件:
java
public static boolean allMatch(int[] arr, IntPredicate predicate)
// 用可变参数重构
public static boolean allMatch(IntPredicate predicate, int... nums)练习 3:挑战题
写一个命令行计算器:
bash
$ java Calc add 3 5
# 输出:8
$ java Calc sub 10 3
# 输出:7
$ java Calc mul 4 5
# 输出:20
$ java Calc div 10 2
# 输出:5下一章:第 12 章:数组 →