Java一个方法中返回多个数据值的实现
本文介绍了在Java中实现方法返回多个值的6种方案:1)自定义对象封装;2)JDK14+的record关键字;3)使用第三方框架如Apache Commons的Pair/Triple类;4)类型一致的List集合;5)键值对Map;6)通过参数传递空对象填充。对比分析了各方案的优缺点,建议非临时场景优先使用自定义类或record,临时简单数据可使用Pair类,而List/Map则适合快速原型开发。
·
日常开发中,我们经常需要在一个方法里返回多个值,在go中,这个很好实现:
func getResult() (string, int) {
return "result", 30
}
在Java中,可考虑以下实现:
1、自定义对象
首先能想到的应该就是封装成一个对象,这里以两个基本数据类型的返回值为例,两个引用数据类型也是一样:
// 自定义类
public class UserInfo {
private final String name;
private final int age;
public UserInfo(String name, int age) {
this.name = name;
this.age = age;
}
// Getters
public String getName() { return name; }
public int getAge() { return age; }
}
// 方法直接返回这个自定义类
public UserInfo getUserInfo() {
return new UserInfo("Alice", 30);
}
// 调用方
UserInfo userInfo = getUserInfo();
String name = userInfo.getName();
int age = userInfo.getAge();
2、JDK14+的record关键字
如果项目中使用的JDK是14+版本,那可以使用record关键字,简化DTO的定义
// 定义 Record(不可变类)
public record UserInfo(String name, int age) {}
// 方法返回 Record
public UserInfo getUserInfo() {
return new UserInfo("Alice", 30);
}
调用方获取值,直接访问字段:
// 调用方
UserInfo userInfo = getUserInfo();
String name = userInfo.name(); // 直接访问字段
int age = userInfo.age();
优点:
- 代码简洁(自动生成 equals()/hashCode()/toString())
- 不可变性(线程安全)
3、第三方框架
很多三方框架中,有类似的现成类提供,比如Apache RocketMQ源码中的Pair类,源码:
package org.apache.rocketmq.common;
public class Pair<T1, T2> {
private T1 object1;
private T2 object2;
public Pair(T1 object1, T2 object2) {
this.object1 = object1;
this.object2 = object2;
}
public T1 getObject1() {
return object1;
}
public void setObject1(T1 object1) {
this.object1 = object1;
}
public T2 getObject2() {
return object2;
}
public void setObject2(T2 object2) {
this.object2 = object2;
}
}
以上封装比较简单,Apache Commons工具包中,还封装了更优的Pair和Triple类,分别用于两个值、三个值的情况,Pair翻译即配对,Triple即三重的

使用示例:
// 使用 Apache Commons Lang3 的 Pair
import org.apache.commons.lang3.tuple.Pair;
public Pair<String, Integer> getUserInfo() {
String name = "Alice";
int age = 30;
return Pair.of(name, age);
}
// 调用方
Pair<String, Integer> userInfo = getUserInfo();
String name = userInfo.getLeft();
int age = userInfo.getRight();
4、使用List
如果返回值类型一致,使用List倒也是一种实现方式,但要考虑下标越界异常的case
public List<String> getUserNameAndEmail() {
String name = "Alice";
String email = "alice@example.com";
return Arrays.asList(name, email); // 或者 List.of(name, email)(Java 9+)
}
// 调用方
List<String> userInfo = getUserNameAndEmail();
String name = userInfo.get(0); // 直接获取,无需转型
String email = userInfo.get(1);
不过这样可读性比较差,从0、1这样的下标,无法直观看到字段语义,临时用一下也行
5、使用Map
使用键值对存,但这样又得维护键的名字,也不是什么最优解:
public Map<String, Object> getUserInfo() {
Map<String, Object> map = new HashMap<>();
map.put("name", "Alice");
map.put("age", 30);
return map;
}
// 调用方
Map<String, Object> userInfo = getUserInfo();
String name = (String) userInfo.get("name"); // 需转型
int age = (int) userInfo.get("age");
6、传一个空壳,由被调方传值
以下只是体现一种思路,即:我拿一个空碗给你,你盛好饭,我开吃
public void getUserInfo(UserInfoHolder holder) {
holder.setName("Alice");
holder.setAge(30);
}
// 调用方
UserInfoHolder holder = new UserInfoHolder();
getUserInfo(holder);
String name = holder.getName();
int age = holder.getAge();
总结下:
| 方案 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 自定义类 | 业务逻辑复用 | 语义清晰,易扩展 | 需额外定义类 |
Record |
JDK 14+ 的不可变数据 | 代码简洁,线程安全 | 需高版本 JDK |
Pair/Triple |
临时简单数据 | 无需定义新类 | 可读性差 |
List/数组 |
快速原型开发 | 代码简短 | 类型不安全 |
Map |
动态键值场景 | 灵活性高 | 键名易错,类型不安全 |
| 参数修改 | 需修改外部状态(不推荐) | 类似 C/C++ 风格 | 破坏封装性 |
非临时使用,建议优先考虑封装自定义类或者Record
更多推荐


所有评论(0)