在 Java 开发中,枚举(enum
)不仅仅是用来定义一组常量。通过参数化枚举常量和实现特定的逻辑,枚举可以变得功能强大且灵活。本文将针对以下两段代码进行详细解析:
枚举常量的参数化定义
FAIL(500, "失败")
枚举值的遍历与查找逻辑
for (ResultCodeEnum resultCodeEnum : ResultCodeEnum.values()) {
if (resultCodeEnum.code == codeVal) {
return resultCodeEnum;
}
}
在 Java 中,枚举(enum
)用于定义一组固定的常量。通常,我们会看到类似以下的简单枚举:
public enum Status {
ACTIVE,
INACTIVE,
PENDING
}
然而,Java 枚举的强大之处在于它允许为每个枚举常量定义参数,从而为每个常量关联特定的数据。这种方式使得枚举不仅仅是简单的常量集合,而是可以携带更多信息的对象。
以您的代码为例:
FAIL(500, "失败")
这里,FAIL
是枚举 ResultCodeEnum
的一个常量,它被参数化为两个值:
code
):500
desc
):"失败"
这种参数化的定义方式使得每个枚举常量不仅有名称(如 FAIL
),还携带了额外的属性信息。
为了支持参数化的枚举常量,需要在枚举中定义相应的字段和构造方法。例如:
@Getter
public enum ResultCodeEnum {
SUCCESS(200, "成功"),
FAIL(500, "失败");
// 状态码
private final int code;
// 描述
private final String desc;
ResultCodeEnum(int code, String desc) {
this.code = code;
this.desc = desc;
}
}
解析:
private final int code;
和 private final String desc;
分别用于存储状态码和描述信息。使用 final
修饰确保这些字段的不可变性。ResultCodeEnum(int code, String desc)
是一个私有构造方法,用于初始化每个枚举常量的 code
和 desc
字段。@Getter
注解:自动为所有字段生成 getter 方法,简化代码编写。private final
字段和 getter 方法,确保了数据的封装与不可变性。在实际应用中,常常需要根据某个值(如状态码)来查找对应的枚举常量。例如,当接收到一个状态码 500
时,需要找到对应的 ResultCodeEnum.FAIL
枚举实例。
以下是您提供的遍历查找逻辑:
public static ResultCodeEnum getByCode(int codeVal) {
for (ResultCodeEnum resultCodeEnum : ResultCodeEnum.values()) {
if (resultCodeEnum.code == codeVal) {
return resultCodeEnum;
}
}
return null;
}
解析:
ResultCodeEnum.values()
方法:
ResultCodeEnum.values()
返回 [SUCCESS, FAIL]
。增强型 for
循环:
for (ResultCodeEnum resultCodeEnum : ResultCodeEnum.values())
遍历所有枚举常量。resultCodeEnum
分别代表 SUCCESS
和 FAIL
。条件判断:
if (resultCodeEnum.code == codeVal)
检查当前枚举常量的 code
是否与传入的 codeVal
相等。返回 null
:
codeVal
,则返回 null
。优点:
缺点:
null
可能导致调用者在未进行 null
检查时发生 NullPointerException
。为了提升查找效率和代码的健壮性,可以考虑以下优化措施:
使用静态缓存(Map):
Map
来缓存 code
与枚举实例的映射关系,将查找时间复杂度降低到 O(1)。private static final Map<Integer, ResultCodeEnum> CODE_MAP = new HashMap<>();
static {
for (ResultCodeEnum resultCodeEnum : ResultCodeEnum.values()) {
CODE_MAP.put(resultCodeEnum.getCode(), resultCodeEnum);
}
}
public static ResultCodeEnum getByCode(int codeVal) {
return CODE_MAP.get(codeVal);
}
使用 Optional
避免返回 null
:
Optional<ResultCodeEnum>
,强制调用者处理可能的空值,减少 NullPointerException
风险。public static Optional<ResultCodeEnum> getByCode(int codeVal) {
return Optional.ofNullable(CODE_MAP.get(codeVal));
}
抛出自定义异常:
public static ResultCodeEnum getByCode(int codeVal) {
ResultCodeEnum result = CODE_MAP.get(codeVal);
if (result == null) {
throw new IllegalArgumentException("无效的状态码: " + codeVal);
}
return result;
}
结合上述两部分的解析,以下是一个完整的 ResultCodeEnum
实现示例:
package com.jingdianjichi.subject.common.enums;
import lombok.Getter;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
/**
* @ClassDescription: 结果码枚举
* @Author: Charlotte
* @Created: 2024/10/2 01:44
*/
@Getter
public enum ResultCodeEnum {
SUCCESS(200, "成功"),
FAIL(500, "失败");
// 状态码
private final int code;
// 描述
private final String desc;
// 静态缓存 Map,用于快速查找
private static final Map<Integer, ResultCodeEnum> CODE_MAP = new HashMap<>();
// 静态代码块,初始化缓存 Map
static {
for (ResultCodeEnum resultCodeEnum : ResultCodeEnum.values()) {
CODE_MAP.put(resultCodeEnum.getCode(), resultCodeEnum);
}
}
// 构造方法
ResultCodeEnum(int code, String desc) {
this.code = code;
this.desc = desc;
}
/**
* 根据状态码获取枚举
* @param codeVal 状态码
* @return 对应的 ResultCodeEnum,如果不存在则返回 Optional.empty()
*/
public static Optional<ResultCodeEnum> getByCode(int codeVal) {
return Optional.ofNullable(CODE_MAP.get(codeVal));
}
}
以下是如何在实际项目中使用 ResultCodeEnum
的示例:
public class ApiResponse {
private int code;
private String message;
private Object data;
// 构造方法
public ApiResponse(int code, String message, Object data) {
this.code = code;
this.message = message;
this.data = data;
}
// 静态方法:成功响应
public static ApiResponse success(Object data) {
return new ApiResponse(ResultCodeEnum.SUCCESS.getCode(), ResultCodeEnum.SUCCESS.getDesc(), data);
}
// 静态方法:失败响应
public static ApiResponse fail(ResultCodeEnum resultCodeEnum) {
return new ApiResponse(resultCodeEnum.getCode(), resultCodeEnum.getDesc(), null);
}
// Getter 和 Setter 略
}
调用示例:
@RestController
@RequestMapping("/api")
public class UserController {
@GetMapping("/user/{id}")
public ResponseEntity<ApiResponse> getUser(@PathVariable Long id) {
Optional<User> userOpt = userService.findById(id);
if (userOpt.isPresent()) {
return ResponseEntity.ok(ApiResponse.success(userOpt.get()));
} else {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(ApiResponse.fail(ResultCodeEnum.FAIL));
}
}
}
—— 评论区 ——