我试图在同一类的Enum的构造函数中访问类的Enum。以下是我找到的解决方法。
Java enum- Cannot reference a field before it is defined
它可以很好地编译,但是由于涉及很多正式代码,因此我尝试用Lambda替换接口实现,但是它编译时不会出现诸如
的错误 Cannot reference a field before it is defined
以下是我做过的lambda替换。
package test;
public enum Baz {
yin(() -> {
return Baz.yang;//doesnt compile. ->Cannot reference a field before it is defined
}),
yang(new OppositeHolder() {
@Override
public Baz getOpposite() {
return yin;
}
}),
good(new OppositeHolder() {
@Override
public Baz getOpposite() {
return evil;//BUT THIS COMPILES JUST FINE, EVEN THOUGH IT ACCESSES evil WHICH HAS BEEN DECLARED LATER.
}
}),
evil(new OppositeHolder() {
@Override
public Baz getOpposite() {
return good;
}
});
private final OppositeHolder oppositeHolder;
private Baz(OppositeHolder oppositeHolder) {
this.oppositeHolder = oppositeHolder;
}
private static interface OppositeHolder {
public Baz getOpposite();
}
}
在lambda表达式的帮助下,有什么我可以做的,因为我可能在此类中看到很多枚举,而且我真的不想重复样板代码。
编辑 我知道该错误意味着我无法访问稍后声明的枚举。另外,我实际上不能将枚举名称存储为字符串,因为这对我来说是一个维护噩梦。另外,我很好奇为什么链接中的示例可以编译,而我的却不能。
答案 0 :(得分:1)
这不能通过简单地用相应的lambda表达式替换匿名接口实现来完成,因为它们并不相同。
lambda主体没有自己的上下文。这是在Java Language Specification, § 15.27.2中定义的:
与出现在匿名类声明中的代码不同,名称的含义以及
this
和super
关键字出现在lambda正文中,以及对引用声明的可访问性,与周围环境相同(除了lambda参数引入新名称)。
(强调我的)
这实际上意味着您遇到与your linked question的OP相同的问题。
我怀疑我是否会遵循你的方法。我个人更喜欢this answer中的代码。
enum Baz {
YIN,
YANG,
GOOD,
EVIL;
private static final Map<Baz, Baz> opposites;
static {
Map<Baz, Baz> m = new EnumMap<>(Baz.class);
m.put(YIN, YANG);
m.put(YANG, YIN);
m.put(GOOD, EVIL);
m.put(EVIL, GOOD);
opposites = Collections.unmodifiableMap(m);
}
public Baz opposite() {
return Optional.ofNullable(opposites.get(this)).get();
}
}
答案 1 :(得分:0)
问题在于即使在lambda调用中,您的using变量也要在定义之前使用。一种解决方法是使用valueOf
public enum Baz {
yin(() -> Baz.valueOf("yang")),
yang(() -> Baz.valueOf("yin")),
good(() -> Baz.valueOf("evil")),
evil(() -> Baz.valueOf("good"))
;
private final OppositeHolder oppositeHolder;
private Baz(OppositeHolder oppositeHolder) {
this.oppositeHolder = oppositeHolder;
}
private static interface OppositeHolder {
public Baz getOpposite();
}
}
public static void main(String... args){
System.out.println(Baz.yin);
System.out.println(Baz.yin.oppositeHolder.getOpposite());
}
输出为
yin
yang