Java中Enum的优雅用法

Java中Enum的优雅用法

本文简单总结一些Java中enum的坑以及优雅的用法。

普通的enum有什么问题

  • 分布式系统中由enum引起的问题
    分布式系统中,系统间调用如果返回值中有enum类型的话,如果服务提供方改变,调用方没有改,就会报错,而且这个本该是业务层面的问题要在系统服务层才能看到报错信息,不利于系统维护。
  • 数据库存储问题
    enum的命名通常都是完整含义的单词,会很长,放数据库中占空间很多,而且不同的中间件存的数据类型也不一样。
  • 和前端的交互问题
    一般的web框架或者json对enum处理要么是字符串(name),要么序数(ordinal),字符串不利于沟通,容易拼写错误
  • 不要用序数(ordinal)
    以上问题都可以用一个通用的解决方法:将enum转成int,有的会支持直接用ordinal,但这并不是最优解法,因为用ordinal就不能随意改动enum定义的顺序,而且还不能自定义值。

优雅用法:带自定义id的enum

优雅的用法是在enum中定义int值,并在构造方法限定int值。举个例子:

/**
 * 性别
 */
public enum Gender {
    /**
     * 男
     */
    MALE(1),
    /**
     * 女
     */
    FEMALE(0),
    /**
     * 保密
     */
    SECURITY(2),
    ;
    private int id;
    Gender(int id) {
        this.id = id;
    }

    public static Gender getInstance(int id) {
        for (Gender tmp : Gender.values()) {
            if (tmp.id == id) {
                return tmp;
            }
        }
        return null;
    }

    public int getId() {
        return id;
    }
}

这样就可以在其他地方获取id,也可以根据id获取对应enum。

通用Enum工具

但是这样每定义一种enum就得写一个getInstance方法,还是不够优雅,处理思路是写一个通用的工具方法来做这个事情。
首先定义一个通用enum的接口:

public interface IdEnum {
    int getId();
}

然后让定义的enum实现这个接口:

/**
 * 性别
 */
public enum Gender implements IdEnum {
    /**
     * 男
     */
    MALE(1),
    /**
     * 女
     */
    FEMALE(0),
    /**
     * 保密
     */
    SECURITY(2),
    ;
    private int id;
    Gender(int id) {
        this.id = id;
    }
    @Override
    public int getId() {
        return id;
    }
}

这里就不需要getInstance方法了,直接利用Java的泛型特性写一个通用的获取方法:

public class EnumUtil {
    public static  T valueOf(Class enumType, int id) {
        for (T value : enumType.getEnumConstants()) {
            if (value.getId() == id) {
                return value;
            }
        }
        return null;
    }
}

你可能感兴趣的:(Java中Enum的优雅用法)