枚举中的非法前向引用

Héc*_*tor 5 java enums

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

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

和另一种选择:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我该如何解决?谢谢.

Rad*_*def 18

有两种可能的解决方案对我来说似乎是合理的.

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

    public enum ParseResource {
        PUSH(Constants.API_URL);
    
        private static class Constants {
            private static final String API_URL = "https://api.parse.com/1";
        }
    
        private String url;
        private ParseResource(String url) { this.url = url; }
    }
    
    Run Code Online (Sandbox Code Playgroud)

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

  2. 使用方法:

    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; }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    使用方法的一个隐藏缺点是方法调用不是常量表达式,因此它不能用于某些事情,例如注释元素值.


还有第三种可行的方法在实践中有效,但是从Java 9起,JLS不再能保证工作,所以不应该使用它.

这使用限定名称ParseResource.API_URL而不是简单名称API_URL来规避前向引用错误,因为它API_URL是一个常量变量(即String在这种情况下用文字初始化):

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; }
}
Run Code Online (Sandbox Code Playgroud)

在Java 8中,这种良好的行为通过指定的8.3.2:

请注意,static作为常量变量的static字段在其他字段之前初始化.[...]永远不会观察到这些字段具有默认的初始值.

但是,由于此错误报告,Java 9中的措辞已更改为以下内容:

请注意,static作为常量变量的static字段在其他字段之前初始化.[...] 当这些字段以简单名称引用时,永远不会观察到它们具有默认的初始值.

上面的代码不受bug报告中描述的缺陷的影响,但是从Java 9开始,它不再保证可以工作.