2016-06-11 1 views
-2
public static <E extends Enum<E>> void example(E e){ 
    e. //what should I put here to get result of values()? 
} 

Я пытаюсь вызвать метод values(), который возвращает значения enum с использованием этого метода с помощью общих аргументов.Как я могу вызывать значения() из экземпляра родового типа <E extends Enum <E>>?

Как я могу это сделать?

ответ

3

Enum не имеет values() способ. Он добавляется компилятором позже в каждый из ваших подклассов Enum (когда мы создаем собственный тип enum YourEnum{...}). Поэтому мы не можем вызывать values() от Enum.

Возможное решение

E[] values = e.getDeclaringClass().getEnumConstants(); 

Чтобы быть в безопасности, мы должны использовать getDeclaringClass() вместо getClass(), потому что значения перечисления могут быть реализованы в виде анонимных классов как в случае TimeUnit

public enum TimeUnit { 
    /** 
    * Time unit representing one thousandth of a microsecond 
    */ 
    NANOSECONDS { 
     public long toNanos(long d) { return d; } 
     public long toMicros(long d) { return d/(C1/C0); } 
     public long toMillis(long d) { return d/(C2/C0); } 
     public long toSeconds(long d) { return d/(C3/C0); } 
     public long toMinutes(long d) { return d/(C4/C0); } 
     public long toHours(long d) { return d/(C5/C0); } 
     public long toDays(long d) { return d/(C6/C0); } 
     public long convert(long d, TimeUnit u) { return u.toNanos(d); } 
     int excessNanos(long d, long m) { return (int)(d - (m*C2)); } 
    }, 

В этом случае

  • TimeUnit.NANOSECONDS.getClass() возвращает java.util.concurrent.TimeUnit$3 (но это анонимный класс не содержит каких-либо значений перечислений)
  • TimeUnit.NANOSECONDS.getDeclaringClass() возвращает java.util.concurrent.TimeUnit (с содержит все значения перечислений).

Это также сэкономит нам некоторые проблемы с литьем, так как

  • getDeclaringClass возвращается Class<E>
  • getClass() возвращает Class<? extends E>

Так привести тип

  • getDeclaringClass().getEnumConstants() является E[]
  • в то время как getClass().getEnumConstants() является ? extends Enum[].

Это позволяет создать цикл, как без необходимости привлечения литья:

for (E value : e.getDeclaringClass().getEnumConstants()){ 
    //handle value 
} 

В качестве дополнительного, вы также можете получить все значения из Class<E> (где <E extends Enum<E>>) с помощью EnumSet.allOf(enumClass) как в код кода с этого вопроса:

EnumSet<E> allOf = EnumSet.allOf(e.getDeclaringClass()); 
+1

Интересное примечание: 'getEnumConstants()' фактически реализуется [вызовом 'values ​​()' в классе enum через отражение] (http://hg.openjdk.java.net /jdk8u/jdk8u/jdk/file/96393e490afd/src/share/classes/java/lang/Class.java#l3307). :-) (Отражение происходит только один раз для каждого класса: значения кэшируются, а 'getEnumConstants()' возвращает защитную копию этих значений для каждого вызова.) –

2

Ну, есть способ в класе Class<T> называется getEnumConstants() который делает именно это.Таким образом, я имел этот метод, который распечатывается константы перечислений для любого значения перечисления здесь:

public <E extends Enum<E>> void printEnums(E e){ 
    for(E value : e.getDeclaringClass().getEnumConstants()){ 
     System.out.println("Value: "+value); 
    } 
} 

Для вызова я хотел бы использовать что-то вроде
printEnums(Enum.SOME_VALUE);

хотя я думаю, что следующий метод лучше, потому что она принимает в качестве параметра класс перечисления непосредственно:

public static <E extends Enum<E>> void printEnums(Class<E> e){ 
    for(E value : e.getEnumConstants()){ 
     System.out.println("Value: "+value); 
    } 
} 

Вы можете назвать этот метод следующим образом: printEnums(EnumClass.class);

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

EDIT 1: Изменил код. Спасибо @JBNizet

EDIT 2: Изменен код еще раз в соответствии с комментарием @ Tunaki. Примечание: изначально он был адресован Pshemo's answer

+1

Тип 'value' должен быть E, а не Enum . Кроме того, e.getClass() следует отнести к классу (его объявленный тип возврата - класс ) –

+0

@JBNizet Вы абсолютно правы! Я редактирую это немедленно! Спасибо, что указали: o –

+1

Первый фрагмент не работает во всех случаях, попробуйте использовать 'printEnums (TimeUnit.MILLISECONDS);'. См. [Ответ Pshemo] (http://stackoverflow.com/a/37765856/1743880), вам нужно использовать 'getDeclaringClass()' – Tunaki

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