Java写一个优雅的枚举类以及枚举类遍历

本文探讨了枚举类相对于静态常量的优势,如增强可读性、类型安全和命名空间。枚举类在表示固定值集合时提供了更好的抽象。同时,通过示例展示了枚举类的遍历性能,并指出在高频率使用场景下,缓存枚举实例可以提升性能。Spring框架中曾因未缓存枚举而导致的性能问题为例,强调了这一点的重要性。
摘要由CSDN通过智能技术生成

为什么要定义枚举类? 

有时候一个类的某些变量的值是有限的、或者固定的,使用数字,可读性差、经常需要去定义的地方查看它的意义,如果代码里没有注释,将会是很痛苦的!此时若定义枚举类,枚举类的名称命名时涵盖该变量的意义,枚举项替代原有的数字或者其他常量项,在读、写代码时友好性大大增加!

示例枚举类定义,将枚举类的方法直接以static修饰!

public class ProductRefEnum {
 
    @Getter
    @AllArgsConstructor
    public enum FunctionType {
 
        /**
         * 功能定义来源枚举,0:模板引入,1:自定义
         */
        MODEL_REF(0, "模板引入"),
        CUSTOM(1, "自定义");
 
        public Integer code;
        public String msg;
 
        private static HashMap<Integer, ProductRefEnum.NodeType> data = new HashMap<>();
 
        static {
            for (ProductRefEnum.FunctionType type : ProductRefEnum.FunctionType.values()) {
                data.put(type.code, type);
            }
        }
 
        public static ProductRefEnum.FunctionType parse(Integer code) {
            if (data.containsKey(code)) {
                return data.get(code);
            }
            return null;
        }
 
    }

    public enum GoodsType {

        WEIGH(1, "按重计价"),
        SIN(2, "按份计价");
        GoodsType(int code, String value) {
            this.code = code;
            this.value = value;
        }

        private int code;
        private String value;

        public int getCode() {
            return this.code;
        }
        public String getValue() {
            return this.value;
        }
    }
}

为什么不用静态常量来替代枚举类呢?

使用常量会有以下几个缺陷:

  1. 类型不安全。若一个方法中要求传入季节这个参数,用常量的话,形参就是int类型,开发者传入任意类型的int类型值就行,但是如果是枚举类型的话,就只能传入枚举类中包含的对象。

  2. 没有命名空间。开发者要在命名的时候以SEASON_开头,这样另外一个开发者再看这段代码的时候,才知道这四个常量分别代表季节。

和静态常量比起来,枚举类更加直观,类型安全!

枚举类遍历

/**
 * 枚举类遍历测试
 *
 */
@State(Scope.Benchmark)
@Warmup(iterations = 3, time = 3)
@Measurement(iterations = 5, time = 3)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class EnumIteration {
    enum FourteenEnum {
        a,b,c,d,e,f,g,h,i,j,k,l,m,n;

        static final FourteenEnum[] VALUES;
        static {
            VALUES = values();
        }
    }

    @Benchmark
    public void valuesEnum(Blackhole bh) {
        for (FourteenEnum value : FourteenEnum.values()) {
            bh.consume(value.ordinal());
        }
    }

    @Benchmark
    public void enumSetEnum(Blackhole bh) {
        for (FourteenEnum value : EnumSet.allOf(FourteenEnum.class)) {
            bh.consume(value.ordinal());
        }
    }

    @Benchmark
    public void cacheEnums(Blackhole bh) {
        for (FourteenEnum value : FourteenEnum.VALUES) {
            bh.consume(value.ordinal());
        }
    }
}

很明显使用缓存后的遍历速度是最快的,使用 EnumSet 遍历效率是最低的,这很好理解,数组的遍历效率是大于哈希表的。

可能你会觉得这里使用 values() 缓存和直接使用 Enum.values() 的效率差异很小,其实在某些调用频率很高的场景下是有很大区别的,在 Spring 框架中,曾使用 Enum.values() 这种方式在每次响应时遍历 HTTP 状态码枚举类,这在请求量大时造成了不必要的性能开销,后来进行了 values() 缓存优化。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值