2016-12-22 7 views
2

У меня есть interface:Общий параметр метода: перечисление, который реализует интерфейс

public interface NamedEnum { 
    String getName(); 
} 

enum который реализует interface: Метод

public enum MyEnum implements NamedEnum { 

    MYVALUE1("My value one"), 
    MYVALUE2("My value two"); 

    private String name; 

    private MyEnum(String name) { 
     this.name = name; 
    } 

    public String getName() { 
     return name; 
    } 
} 

, который не компилируется:

public static Map<Integer,String> wrong(Enum<? extends NamedEnum> value) { 
    Map<Integer,String> result = new LinkedHashMap<Integer, String>(); 
    for (Enum<? extends NamedEnum> val : value.values()) 
     result.put(val.ordinal(), val.getName()); 
    return result; 
} 

Две ошибки:

The method values() is undefined for the type Enum<capture#1-of ? extends NamedEnum> The method getName() is undefined for the type Enum<capture#3-of ? extends NamedEnum>

Я не могу понять, как описанный выше способ может принимать enum который реализует interface.

+0

Следует, наверное, указать, что вы можете не использовать 'порядковый номер '. Цитирование Javadoc: «Большинство программистов не будут использовать этот метод. Он предназначен для использования сложными структурами данных на основе enum, такими как EnumSet и EnumMap». Вы не сказали, что делаете, но обратите внимание. Кроме того, проверьте * Эффективная Java 2nd ed * Пункт 33: «Используйте EnumMap вместо порядкового индексации». –

+0

* «Ты не сказал, что делаешь» *: Я думал, что это будет бессмысленно, но это не так. Хорошо ... перезагрузитесь! Я прыгнул с Java6 до 8, и я пропустил некоторые промежуточные. Я не знал о * множественной привязке в generics *, но я уже видел цитату 'ordinal' в javaDoc, но я был ленив и не проверял« EnumSet/Map »: мой плохой. Мне нужно мое перечисление для создания select/options, такого как '' и так далее ... Я понимаю, что я могу сделать это просто так: ' 'и получить значения с помощью' valueOf ("MYVALUE1") '. – fantaghirocco

+0

Здесь нет ничего нового, поскольку Java 6 (см. [Типы пересечений в JLS] (https://docs.oracle.com/javase/specs/jls/se6/html/typesValues.html#4.9)). Кроме того, EJ 2nd Ed был написан для Java 6. Но да, за то, что вы говорите, что вы делаете, использование имен перечислений намного лучше, чем ординалы. –

ответ

7

Определить переменный тип с типом пересечения:

public static <E extends Enum<E> & NamedEnum> Map<Integer,String> wrong(E value) { 

Но обратите внимание, что это проходит элемент перечисления, а не перечисление самого класса. Вы можете использовать:

public static <E extends Enum<E> & NamedEnum> Map<Integer,String> wrong(Class<E> clazz) { 

, а затем использовать clazz.getEnumConstants(), чтобы получить значения перебрать:

for (E val : clazz.getEnumConstants()) 

В качестве альтернативы, вы можете использовать value.getDeclaringClass().getEnumConstants().

3

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

IIUC, вы ищете способ получить значение, возвращаемое getName() на основе порядкового номера перечисления. Другими словами, вы ищете отображения, такие как это:

  • 0 => "My Value один"
  • 1 => "Мой значение два"

Если это действительно case, то как насчет использования массива значений enum напрямую (массив индексируется по порядковым значениям enum). Например:

NamedEnum[] arr = MyEnum.values(); 
System.out.println(arr[0].getName()); // Output: "My value one" 
System.out.println(arr[1].getName()); // Output: "My value two" 

Заметим, что переменная arr могут быть назначены из различных перечислений (до тех пор, как они реализуют интерфейс NamedEnum). Например, если у вас есть этот другой перечисление определено в программе:

public enum MyOtherEnum implements NamedEnum { 

    MYVALUE3("My other value three"), 
    MYVALUE4("My other value four"); 

    private String name; 

    private MyOtherEnum(String name) { 
     this.name = name; 
    } 

    @Override 
    public String getName() { 
     return name; 
    } 
} 

Тогда следующий действительный основной() метод:

public static void main(String[] args) { 
    NamedEnum[] arr = MyEnum.values(); 
    System.out.println(arr[0].getName()); 
    System.out.println(arr[1].getName()); 

    arr = MyOtherEnum.values(); 
    System.out.println(arr[0].getName()); 
    System.out.println(arr[1].getName()); 
} 

Выход, как и ожидалось является:

My value one 
My value two 
My other value three 
My other value four 

Надеюсь, что это поможет.

+0

Это позволяет вам смешивать содержимое массива из разных перечислений: 'new NamedEnum [] {MyEnum.MYVALUE1, MyEnum2.MYVALUE3}'. Независимо от того, важно это или нет, зависит от приложения. –

+0

* «вы ищете способ получить значение, возвращаемое getName() на основе порядкового номера перечисления» *, не совсем то же самое ... Мне нужно либо «имя», либо «порядковый номер». Что делать, если реализация Java 'Enum' изменится, что позволит назначать ординалы? Просто дикая догадка, но некоторые языки позволяют это (например, Delphi). Спасибо за ваш ответ. Upvoted – fantaghirocco

+0

@AndyTurner - Исходя из кода неправильного метода(), отправляемого на вопрос, после того как возвращается переменная 'result', вызывающий код заканчивается« Map », который так же подвержен к этому типу смешивания. –

Смежные вопросы