У меня есть два класса 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
}
}
Вы не можете делать то, что пытаетесь. Во-первых, переключатель 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();
}
}
Вам нужно будет указать перечисление на определенный тип перед оператором switch (и, следовательно, иметь отдельный оператор switch для каждого типа). Это сказало, что это не лучшее из идей. Вероятно, вы найдете лучшее решение, рефакторинг кода, так что вам не нужно это делать.
Указанный вами переключатель явно не работает.
У меня есть (довольно странная) подстановка: создайте "хелперное перечисление", которое содержит все перечисленные значения и имеет 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: ....
}
(аналогичная версия впервые опубликована здесь)
Было бы полезно иметь общий интерфейс, реализуемый перечисленными перечислениями, но этот, вероятно, тоже будет работать.