【Java编程】用枚举类初始化内部类的坑

问题

年底写了一个程序,由于代码库经常有人将枚举类当中的各项数值进行分类,存储到相应的map当中。

然后快速用key判断或者拿到实例。

在重构的过程中,发现访问这个Map的时候,其实是空的。

System.out.println(MonitorEnum.MetaData.flinkMonitorMap.size()); // 输出 0
public enum MonitorEnum {
    A("flink", "source_rps"),
    B("flink", "checkpoint_failed");

    public static final class MetaData {
        public static final Map<String, MonitorEnum> flinkMonitorMap = new HashMap<>(); //数据在这
    }

    private final String type;
    private final String name;

    MonitorEnum(String type, String name) {
        this.type = type;
        this.name = name;
        if ("flink".equals(type)) {
            MetaData.flinkMonitorMap.put(name, this); //初始化在这
        }
    }
}

分析

看到这种问题,立马想到初始化的问题。于是询问Claude,Claude自己都没发现问题。。。于是把现象告诉GPT,GPT却很快理解了这个问题。

MonitorEnum.values();
System.out.println(MonitorEnum.MetaData.flinkMonitorMap.size()); // 输出 2

解决

应当在MetaData当中初始化这个Map

public static final class MetaData {
        public static final Map<String, MonitorEnum> flinkMonitorMap = new HashMap<>();
        static {
            for (MonitorEnum e : MonitorEnum.values()) {
                if ("flink".equals(e.type)) {
                    flinkMonitorMap.put(e.name, e);
                }
            }
        }
    }

总结

JVM在访问MetaData的时候,并不会直接初始化MonitorEnum,即便MetaData在MonitorEnum的“内部”。对于JVM来说不过是MonitorEnum$MetaData 另一个类型而已。

在明确的规则之下,程序设计应该是责任明确的。

posted @ 2026-01-11 16:16  一杯半盏  阅读(6)  评论(0)    收藏  举报