文章目录
- [一、什么是 Object... args?](#一、什么是 Object... args?)
- [二、Object... args 的本质是什么?](#二、Object... args 的本质是什么?)
- [三、Object... args 的基本用法](#三、Object... args 的基本用法)
- [四、Object... args 在方法内部如何使用?](#四、Object... args 在方法内部如何使用?)
- [五、Object... args 的语法规则](#五、Object... args 的语法规则)
- [六、真实业务场景:Spring Boot + Redis Lua](#六、真实业务场景:Spring Boot + Redis Lua)
- [七、Object... args 与 Object[] 的对比](#七、Object... args 与 Object[] 的对比)
- 八、常见误区与坑点
- 九、总结
在 Java 开发过程中,你几乎不可避免地会看到下面这样的代码:
java
public Long execute(LuaScriptEnum scriptEnum,
List<String> keys,
Object... args)
第一次看到 Object... args,很多人都会感到困惑:
- 方法明明定义了 3 个参数,为什么调用时只传 2 个也不报错?
Object... args到底是不是必须要传?- 它和
Object[]有什么区别? - 为什么 Spring、RedisTemplate、JUnit、日志框架中大量使用这种写法?
事实上,Object... args 并不是某种"高级技巧",
而是 Java 在语言层面为了解决 参数数量不固定 这一常见问题而提供的一种机制。
一、什么是 Object... args?
在 Java 方法定义中:
java
public void test(Object... args) {
}
Object... args 被称为 可变参数(Varargs)。
一句话概括
Object... args表示:这个方法可以接收 0 个、1 个或多个参数
它并不是一种新的数据类型,而是 Java 提供的一种 语法糖。
二、Object... args 的本质是什么?
1、本质等价于数组
java
Object... args
在语义层面上等价于:
java
Object[] args
两者的唯一区别在于:
- 一个是 对调用者友好
- 一个是 对实现者友好
2、编译器到底帮你做了什么?
你写的代码:
java
test(1, "abc", true);
在编译阶段会被转换为:
java
test(new Object[]{1, "abc", true});
👉 可变参数本质上就是编译器自动帮你创建数组
三、Object... args 的基本用法
1、方法定义
java
public void printArgs(Object... args) {
for (Object arg : args) {
System.out.println(arg);
}
}
2、调用方式(重点)
① 不传任何参数(完全合法)
java
printArgs();
等价于:
java
printArgs(new Object[]{});
② 传 1 个参数
java
printArgs(10);
③ 传多个参数
java
printArgs(1, "hello", true);
四、Object... args 在方法内部如何使用?
1、当数组使用(最常见)
java
public void test(Object... args) {
System.out.println(args.length);
}
args.length == 0→ 没有传参数args.length > 0→ 至少传了一个参数
2、判断是否传参(实战必用)
java
public void test(Object... args) {
if (args.length == 0) {
return;
}
// 处理参数
}
👉 不需要判空,Java 保证 args 一定不为 null
五、Object... args 的语法规则
1、只能放在参数列表的最后
❌ 错误写法:
java
public void test(Object... args, String name) {
}
✅ 正确写法:
java
public void test(String name, Object... args) {
}
1、一个方法只能有一个可变参数
❌ 错误示例:
java
public void test(Object... a, Object... b) {
}
3、可变参数可以和普通参数共存
java
public void test(int id, String type, Object... args) {
}
六、真实业务场景:Spring Boot + Redis Lua
在 Spring Boot 中执行 Redis Lua 脚本时,常见封装方式如下:
java
public Long execute(LuaScriptEnum scriptEnum,
List<String> keys,
Object... args)
1、参数含义说明
| 参数 | 含义 |
|---|---|
| scriptEnum | 标识使用哪个 Lua 脚本 |
| keys | Redis 中的 KEYS |
| args | Redis Lua 中的 ARGV(可选) |
2、不传 ARGV 的情况
java
execute(
LuaScriptEnum.STOCK_DEDUCT,
Collections.singletonList("product:stock:1")
);
Lua 中对应关系:
text
KEYS[1] = product:stock:1
ARGV = 空
3、传 1 个 ARGV
java
execute(
LuaScriptEnum.STOCK_DEDUCT,
Collections.singletonList("product:stock:1"),
2
);
Lua 中:
text
ARGV[1] = "2"
4、传多个 ARGV
java
execute(
LuaScriptEnum.SOME_SCRIPT,
Arrays.asList("key1", "key2"),
10, "abc", true
);
Lua 中:
text
ARGV[1] = "10"
ARGV[2] = "abc"
ARGV[3] = "true"
七、Object... args 与 Object[] 的对比
| 对比项 | Object... args | Object[] |
|---|---|---|
| 本质 | 数组 | 数组 |
| 调用方式 | 简洁自然 | 繁琐 |
| 是否可省略 | ✅ 可以 | ❌ 不行 |
| 适合场景 | API 设计 | 内部实现 |
👉 对外暴露的方法,优先使用可变参数
八、常见误区与坑点
1、args 可能为 null?❌
java
if (args == null) {
}
👉 没有必要,args 永远不会是 null
2、 传 null 等于不传参数?❌
java
execute(enum, keys, null);
实际效果:
text
ARGV[1] = "null"
⚠️ 这是传了一个参数,而不是没传
九、总结
为什么优秀的 API 都爱用 Object... args?
- 参数数量不固定
- 调用方代码更简洁
- 向后扩展更友好
- 非常适合"执行器 / 工具类 / 框架 API"
java
execute(script, keys);
execute(script, keys, 1);
execute(script, keys, 1, 2);
Object... args是 Java 为了解决参数不固定问题而提供的语法糖,
本质仍然是数组,但极大提升了 API 的可用性与可读性。
在 Spring Boot、Redis Lua、日志框架、测试框架 等场景中,它几乎是不可或缺的设计方式。