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; }
}