在lambda中的枚举构造函数中访问相同类的枚举不会编译

时间:2019-03-14 12:06:56

标签: java enums

我试图在同一类的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表达式的帮助下,有什么我可以做的,因为我可能在此类中看到很多枚举,而且我真的不想重复样板代码。

编辑 我知道该错误意味着我无法访问稍后声明的枚举。另外,我实际上不能将枚举名称存储为字符串,因为这对我来说是一个维护噩梦。另外,我很好奇为什么链接中的示例可以编译,而我的却不能。

2 个答案:

答案 0 :(得分:1)

这不能通过简单地用相应的lambda表达式替换匿名接口实现来完成,因为它们并不相同。

lambda主体没有自己的上下文。这是在Java Language Specification, § 15.27.2中定义的:

  

与出现在匿名类声明中的代码不同,名称的含义以及thissuper关键字出现在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