оператор switch для соединения различных классов enum в Java

2

У меня есть два класса enum, например Enum1 и Enum2:

enum Enum1 {ONE, TWO, THREE}
enum Enum2 {FOUR, FIVE}

, и у меня есть такой метод:

public <E extends Enum<E>> method (E arg) {
    switch (arg) {    // Here is the compile error -- Cannot switch
                      // on a value of type E. Only convertible int
                      // values, strings or enum variables are permitted

                      // (And of course, all the cases are incorrect
                      // because the enum set is unknown)
        case ONE:
            // do something
        case TWO:
            // do something
        case THREE:
            // do something
        case FOUR:
            // do something
        case FIVE:
            // do something
        default:
            // do something
    }
}

Итак, можно ли переключить значение общего типа перечисления?


Существует один способ изменить его на строки (работает только в JDK7):

public <E extends Enum<E>> method (E arg) {
    switch (arg.name()) {
        case "ONE":
            // do something
        case "TWO":
            // do something
        case "THREE":
            // do something
        case "FOUR":
            // do something
        case "FIVE":
            // do something
        default:
            // do something
    }
}
  • 0
    Вы смотрели какую-нибудь документацию Enum?
  • 6
    Даже если бы это было возможно, два перечисления не связаны друг с другом. Вы не можете проверить Enum1 против значения FOUR или FIVE. Так что ваш код не имеет смысла написано таким образом.
Показать ещё 2 комментария
Теги:
switch-statement
enums

3 ответа

5
Лучший ответ

Вы не можете делать то, что пытаетесь. Во-первых, переключатель enum на самом деле является сокращением для переключения на ordinal() перечисления. Поэтому, даже если вы можете заставить коммутатор распознать свой тип "совместное перечисление", оператор имеет дубликаты ветвей case. (Например, ONE и FOUR оба имеют порядковый номер 0.)

Один подход может состоять в том, чтобы переместить действие в самих перечислений. Затем вы можете использовать каждый тип типа enum для общего интерфейса:

interface Actor {
    void doSomething();
}

enum Enum1 implements Actor {
    ONE {
        public void doSomething() { . . . }
    },
    TWO {
        public void doSomething() { . . . }
    },
    THREE {
        public void doSomething() { . . . }
    }
}

enum Enum2 implements Actor {
    FOUR {
        public void doSomething() { . . . }
    },
    FIVE {
        public void doSomething() { . . . }
    }
}

Затем вы можете реализовать свой метод, чтобы просто делегировать обработку актеру:

public void method(Actor actor) {
    if (actor == null) {
         // default action
    } else {
        actor.doSomething();
    }
}
  • 0
    Хорошая идея, спасибо @Ted
2

Вам нужно будет указать перечисление на определенный тип перед оператором switch (и, следовательно, иметь отдельный оператор switch для каждого типа). Это сказало, что это не лучшее из идей. Вероятно, вы найдете лучшее решение, рефакторинг кода, так что вам не нужно это делать.

  • 0
    Да, я знаю. Я не буду делать это в реальном проекте, я просто пробую язык. Поскольку все типы перечислений неявно получены из java.lang.Enum, поэтому я думаю, что должны быть некоторые общие отношения между различными типами перечислений, и я попробовал это. Таким образом, в JDK7 есть способ сделать это - включить arg.name () и заключить в кавычки все в операторах case (name () получает строку, представляющую именно то, что объявлено в объявлении enum) - конечно, это некоторые тривиальные выводы, но просто для удовольствия!
0

Указанный вами переключатель явно не работает.

У меня есть (довольно странная) подстановка: создайте "хелперное перечисление", которое содержит все перечисленные значения и имеет Map<Request<Enum<?>, HelperEnum>, например:

private enum HelperEnum {
       ONE(Enum1.ONE),
       TWO(Enum1.TWO),
       THREE(Enum1.THREE),
       FOUR(Enum2.FOUR),
       FIVE(Enum2.FIVE);

       private Enum<?> source;

       private HelperEnum(Enum<?> source) {
           this.source = source;
       }

       private static Map<Enum<?>, HelperEnum> map;

       public static HelperEnum lookUp(Enum<?> source) {
           if (map == null) {
               map = Arrays.stream(HelperEnum.values())
                   .collect(Collectors.toMap(x -> x.source, x -> x));
           }
           return map.get(source);
       }

(непроверенные!)

Таким образом, вы можете сделать

switch(HelperEnum.lookUp(a_request)){
    case ONE: ....
    case TWO: ....
    case THREE: ....
    case FOUR: ....
    case FIVE: ....
}

(аналогичная версия впервые опубликована здесь)

Было бы полезно иметь общий интерфейс, реализуемый перечисленными перечислениями, но этот, вероятно, тоже будет работать.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню