Java 枚举中的非法前向引用

Java 枚举中的非法前向引用,java,enums,Java,Enums,我有一个枚举,我试图在构造函数中传递一个最终的静态变量作为参数。问题是枚举中的第一条语句必须是实例本身,但在这种情况下,还并没有定义最终变量。查看代码,您将了解: public enum ParseResource { PUSH(API_URL); //Error: illegal forward reference private final static String API_URL = "https://api.parse.com/1"; private St

我有一个枚举,我试图在构造函数中传递一个最终的静态变量作为参数。问题是枚举中的第一条语句必须是实例本身,但在这种情况下,还并没有定义最终变量。查看代码,您将了解:

public enum ParseResource {

    PUSH(API_URL); //Error: illegal forward reference

    private final static String API_URL = "https://api.parse.com/1";

    private String url;
    private ParseResource(String url) {
        this.url = url;
    }
}
另一种选择是:

public enum ParseResource {

    //Illegal in enums, first statement has to be an instance
    private final static String API_URL = "https://api.parse.com/1";

    PUSH(API_URL);

    private ParseResource(String url) {
        this.url = url;
    }
}

我怎样才能解决它?谢谢。

我认为有两种可能的解决方案是合理的

  • 使用嵌套类(单独初始化):

    这是最常用的,因为它没有施加任何重要的限制

  • 使用以下方法:

    public enum ParseResource {
        PUSH(getApiUrl());
    
        private static String getApiUrl() { return "https://api.parse.com/1"; }
    
        private String url;
        private ParseResource(String url) { this.url = url; }
    }
    
    使用方法的一个隐藏的缺点是,方法调用不是一个函数,因此它不能用于某些事情,例如注释元素值


  • 还有第三种可能的方法在实践中有效,但从Java9开始,JLS不再保证其有效,因此不应该使用它

    这使用了限定名称
    ParseResource.API_URL
    而不是简单名称
    API_URL
    来避免前向引用错误,因为
    API_URL
    是一个(即在这种情况下,用
    字符串
    文本初始化):

    在Java 8中,这一良好行为由以下内容指定:

    请注意,作为常量变量的
    static
    字段在初始化其他
    static
    字段之前进行初始化。[…]此类字段将永远不会被观察到具有默认初始值

    但是,措辞改为:

    请注意,作为常量变量的
    static
    字段在初始化其他
    static
    字段之前进行初始化。[…]当这些字段被简单名称引用时,将永远不会看到它们有默认的初始值


    上面的代码没有受到bug报告中描述的缺陷的影响,但从Java 9开始,它不再保证工作。

    Enum是一种语法糖,基本上允许您编写更好的switch语句,以及迭代某个类的编译时值集


    在这种情况下,您可以在类中定义编译时字符串,如
    常量
    ——当您面临此类编译问题时,一般规则是,您不应该以这种方式使用enum,并且需要其他类

    想到的解决方案是:不要将url放在枚举中的静态字段中。将它放在枚举之外或构造函数中,或者直接在实例字段之前声明静态最终常量,并将其作为完全限定常量访问。它奇怪地工作;-)在java 9及以上版本中,
    PUSH.url
    在该示例中可能是
    null
    ,因为
    API\u url
    可能在枚举常量初始化之后分配。是的,给出的示例enum看起来有点奇怪,但我认为您的“一般规则”不存在。从更广泛的意义上讲,关于enum,涉及到更多的机制和用例。仔细看看。
    public enum ParseResource {
        PUSH(getApiUrl());
    
        private static String getApiUrl() { return "https://api.parse.com/1"; }
    
        private String url;
        private ParseResource(String url) { this.url = url; }
    }
    
    public enum ParseResource {
        PUSH(ParseResource.API_URL);
    
        private static final String API_URL = "https://api.parse.com/1";
    
        private String url;
        private ParseResource(String url) { this.url = url; }
    }