为啥直到类回调被击中后才构造 java 枚举?

Posted

技术标签:

【中文标题】为啥直到类回调被击中后才构造 java 枚举?【英文标题】:Why is a java enum not constructing till after a class callback is hit?为什么直到类回调被击中后才构造 java 枚举? 【发布时间】:2012-06-19 17:11:24 【问题描述】:

我有一个 android 类,它有一个来自异步 HTTP 进程的回调,以及一个带有多个状态代码的枚举:

public abstract class HttpPackage 

    public enum StatusCode 
        SUCCESS(0),
        NOT_FOUND(100),
        USERNAME_NOT_FOUND(101),
        AUTH_FAILED(110),
        SAVE_ERROR(111)
        //etc.

        private final int mCode;

        StatusCode(int i) 
            mCode = i;
            sByCode.put(i, this);
        

    

    private static final HashMap<Integer, StatusCode> sByCode = new HashMap<Integer, StatusCode>();

    //...

我发现 HttpPackage 类中的回调在 enum 构造之前被命中,这意味着当我尝试从静态代码映射中提取状态代码时,它返回 null,我的代码认为所有提要失败(当它们没有失败时)。为什么这个enum会在回调被命中后构造?

【问题讨论】:

当你已经有一个状态码枚举时,为什么还要麻烦有一个状态码的外部映射?为什么不将它保存在枚举中? 它不会编译。我刚刚发现删除 static 修饰符会有所帮助,但这让我没有静态方式来访问地图。 你通过枚举访问它。 没有静态方式。见下文。 【参考方案1】:

类在 Java 中是延迟加载的。如果您在加载 StatusCode 类之前访问地图,那么它当然是空的。

地图应该在枚举本身中。这样,如果您正在访问地图,则可以保证枚举类已加载,并且地图不为空。地图也应该对外部代码隐藏。你应该在枚举中提供一个静态的StatusCode getByCode(int code) 方法。

编辑:示例代码:

public enum StatusCode 
    SUCCESS(0),
    NOT_FOUND(100),
    USERNAME_NOT_FOUND(101),
    AUTH_FAILED(110),
    SAVE_ERROR(111);

    private final int code;

    private static final Map<Integer, StatusCode> map = new HashMap<Integer, StatusCode>();

    static 
        for (StatusCode sc : values()) 
            map.put(sc.getCode(), sc);
        
    

    StatusCode(int i) 
        this.code = i;
    

    public static StatusCode getByCode(int code) 
        return map.get(code);
    

    public int getCode() 
        return code;
    

    public static void main(String[] args) 
        System.out.println(StatusCode.getByCode(111));
    

或者您也可以在构造函数中使用 getMap() 静态方法,如果地图为空,则延迟初始化地图。

【讨论】:

另外,请记住,泛型类型参数在编译时会被删除,因此 sByCode 不会在运行时引用 StatusCode 类,这会导致在访问地图时加载该类。跨度> 如果我将sByCode 设为静态,它不会在enum 构造函数中初始化,如果我不将其设为静态,getByCode 方法将看不到它。有什么想法吗? 我已经使用简单的“遍历values() 并检查是否相等,返回匹配”方法解决了这个问题,但不能使用HashMap 似乎很遗憾。 @AndrewWyld 我见过的典型解决方法是使 sByCode 成为枚举类的静态成员,然后在静态初始化程序块中用枚举值填充它。 啊,静态初始化器。没想到。谢谢!

以上是关于为啥直到类回调被击中后才构造 java 枚举?的主要内容,如果未能解决你的问题,请参考以下文章

为啥枚举可以有包私有构造函数?

为啥Java抽象类中需要受保护的构造函数

在构造函数中进行 GWT 异步回调安全吗?

java中,当实例化子类时会递归调用父类中的构造方法。这个说法对么?为啥

如果类具有参数化构造函数,为啥Java不提供默认构造函数? [复制]

为啥我的派生类构造函数被删除了?