Перечисление enum внутри одного класса внутри конструктора enum в лямбде не компилируется - PullRequest
1 голос
/ 14 марта 2019

Я пытаюсь получить доступ к Enum класса внутри конструктора Enum того же класса.Вот способ, который я нашел, чтобы сделать это.

Java enum - Невозможно сослаться на поле, пока оно не определено

, которое компилируется просто отлично, но так как в нем многоформального кода я попытался заменить реализации интерфейса лямбда-кодом, но он не компилируется с ошибкой, такой как

Cannot reference a field before it is defined

Ниже приводится лямбда-замена, которую я сделал.

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

}

Есть ли что-нибудь, что я мог бы сделать с помощью лямбда-выражений, так как я мог видеть много перечислений в этом классе, и я действительно не хочу повторять "котел"код.

РЕДАКТИРОВАТЬ Я знаю, что ошибка означает, что я не могу получить доступ к Enum, который был объявлен позже.Кроме того, я не могу сохранить имя enum в виде строки, так как для меня это будет кошмар обслуживания.Кроме того, мне любопытно, почему пример в ссылке компилируется, а мой нет.

Ответы [ 2 ]

1 голос
/ 14 марта 2019

Этого нельзя добиться, просто заменив реализации анонимного интерфейса соответствующими лямбда-выражениями, поскольку они не совпадают.

Тело лямбда-выражения не имеет своего собственного контекста.Это определено в Спецификации языка Java, § 15.27.2 :

В отличие от кода, появляющегося в объявлениях анонимного класса, значения имен и this и superключевые слова, появляющиеся в лямбда-теле, вместе с доступностью ссылочных объявлений , такие же, как в окружающем контексте (за исключением того, что лямбда-параметры вводят новые имена).

(Выделение мое)

Это означает, что у вас фактически такая же проблема, как у ОП ваш связанный вопрос .


Я сомневаюсь, что смогуследовать вашему подходу.Я лично предпочитаю код из этого ответа .

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();
    }
}
0 голосов
/ 14 марта 2019

проблема в том, что вы используете переменную до того, как они определены, даже если это лямбда-вызов.Обходной путь может быть использован 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...