一、什么是枚举?
枚举(enum
)是 Java 中一种特殊的类,用于定义一组固定的常量。枚举类型提供了更好的类型安全性和可读性,适用于需要定义一组有限且固定的值的场景。枚举常量是 public static final
的,可以直接通过枚举类名访问。
枚举的主要特点:
类型安全:限制了变量的取值范围,避免了无效值的传入。
代码简洁:枚举可以代替大量的常量定义,使代码更简洁。
易于维护:枚举将相关的常量集中在一起,便于维护扩展。
二、枚举的基本使用方法
定义枚举
通过 enum
关键字定义,语法如下:
public enum 枚举名 {
常量1,
常量2,
常量3;
}
例如:星期
public enum Week {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
}
另外,枚举还可以定义属性和方法,甚至可以定义构造函数。例如:
public enum Status {
ACTIVE(1, "激活"),
INACTIVE(2, "未激活");
private int code;
private String description;
// 枚举的构造函数
Status(int code, String description) {
this.code = code;
this.description = description;
}
public int getCode() {
return code;
}
public String getDescription() {
return description;
}
}
枚举类继承自 java.lang.Enum
,有一些自带的方法:比如 name()
、ordinal()
、values()
、valueOf(String)
。不过我一般比较少使用这些方法,实际中我会按下面使用枚举。
三、实际使用场景
代替常量
枚举可以用来替代传统的常量定义(如 public static final int
),提供更好的可读性和类型安全性。
状态机
表示有限的状态,比如状态、类型等业务数据。例如:
public enum Status
{
OK("0", "正常"), DISABLE("1", "停用"), DELETED("2", "删除");
private final String code;
private final String info;
Status(String code, String info)
{
this.code = code;
this.info = info;
}
public String getCode()
{
return code;
}
public String getInfo()
{
return info;
}
public static String getInfoByCode(String code){
for (Status value : values()) {
if (code.equals(value.code))return value.info;
}
return null;
}
public static List<String> getCodeList(){
List<String> codeList = new ArrayList<>();
for (Status value : Status.values()) {
codeList.add(value.getCode());
}
return codeList;
}
}
四、更多用法
1.实现接口
枚举可以实现接口,从而扩展功能。
像上文中自定义方法 getCode()
、getInfo()
、getInfoByCode()
和 getCodeList()
都是单独为这个枚举创建的。
我们可以定义一个通用的接口。
public interface KeyValueEnum<K, V> {
K getKey();
V getValue();
}
然后枚举类可以修改为:
public enum Status implements KeyValueEnum<String, String> {
OK("0", "正常"), DISABLE("1", "停用"), DELETED("2", "删除");
private String key;
private String value;
Status(String key, String value) {
this.key = key;
this.value = value;
}
@Override
public String getKey() {
return key;
}
@Override
public String getValue() {
return value;
}
}
getInfoByCode()
和 getCodeList()
可以创建为工具类。
import java.util.ArrayList;
import java.util.List;
public class EnumUtils {
/**
* 根据 key 获取枚举的 value
*
* @param enumClass 枚举类
* @param key key
* @param <K> key 类型
* @param <V> value 类型
* @param <E> 枚举类型
* @return 对应的 value,如果未找到则返回 null
*/
public static <K, V, E extends Enum<E> & KeyValueEnum<K, V>> V getValueByKey(Class<E> enumClass, K key) {
for (E value : enumClass.getEnumConstants()) {
if (value.getKey().equals(key)) {
return value.getValue();
}
}
return null;
}
/**
* 根据 value 获取枚举的 key
*
* @param enumClass 枚举类
* @param value value
* @param <K> key 类型
* @param <V> value 类型
* @param <E> 枚举类型
* @return 对应的 key,如果未找到则返回 null
*/
public static <K, V, E extends Enum<E> & KeyValueEnum<K, V>> K getKeyByValue(Class<E> enumClass, V value) {
for (E e : enumClass.getEnumConstants()) {
if (e.getValue().equals(value)) {
return e.getKey();
}
}
return null;
}
/**
* 获取枚举类的所有 key 值
*
* @param enumClass 枚举类
* @param <K> key 类型
* @param <V> value 类型
* @param <E> 枚举类型
* @return 包含所有 key 的列表
*/
public static <K, V, E extends Enum<E> & KeyValueEnum<K, V>> List<K> getKeyList(Class<E> enumClass) {
List<K> keyList = new ArrayList<>();
for (E value : enumClass.getEnumConstants()) {
keyList.add(value.getKey());
}
return keyList;
}
}
使用工具类:
public class Main {
public static void main(String[] args) {
// 获取 Status 枚举的所有 key 值
List<String> keyList = EnumUtils.getKeyList(Status.class);
System.out.println(keyList); // 输出 ["0", "1", "2"]
// 根据 key 获取 value
String statusValue = EnumUtils.getValueByKey(Status.class, 1);
System.out.println(statusValue); // 输出 "停用"
// 根据 value 获取 key
Integer statusKey = EnumUtils.getKeyByValue(Status.class, "正常");
System.out.println(statusKey); // 输出 0
}
}
2.单例模式
枚举可以用来实现单例模式,确保一个类只有一个实例。
public enum Singleton {
INSTANCE;
public void example() {
System.out.println("枚举实现单例模式");
}
}
那么,为什么枚举可以实现单例模式呢?
枚举(enum)作为单例模式是一种非常优雅且安全的实现方式。主要是因为:
- 枚举常量在 JVM 中是唯一的,每个枚举常量都是枚举类的一个实例。
- 枚举常量在类加载时被初始化,且只会初始化一次。
- 枚举的构造函数是私有的,无法通过反射或手动调用构造函数创建新的实例。
- 枚举的序列化和反序列化由 JVM 保证,反序列化时不会创建新的实例。
3.策略模式
枚举可以用来实现简单的策略模式,每个枚举常量可以定义自己的行为。
比如:进行一些运算。
public enum Operation {
ADD {
public int apply(int a, int b) {
return a + b;
}
},
SUBTRACT {
public int apply(int a, int b) {
return a - b;
}
};
public abstract int apply(int a, int b);
}
总结
枚举的使用可以使代码的可读性更高,更易于维护,并且可以进行一些特定的扩展。但是要注意枚举的使用场景,如果常量特别多或者会频繁变化的值,就不适合使用枚举。