Как я могу получить значение Enum, если я не знаю класс во время компиляции? - PullRequest
19 голосов
/ 10 марта 2011

Я пытаюсь сделать следующее:

Class<?> cls = unknownClass;
if(cls.isEnum()){
    @SuppressWarnings("unchecked")
    Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>) cls;
    Object val = Enum.valueOf(enumClass, "NAME1");
}

Но я получаю следующую ошибку:

Bound mismatch: The generic method valueOf(Class<T>, String) of type Enum<E> is 
not applicable for the arguments (Class<capture#5-of ? extends Enum<?>>, String). 
The inferred type capture#5-of ? extends Enum<?> is not a valid substitute for 
the bounded parameter <T extends Enum<T>>   

Может кто-нибудь сказать мне, что я делаю неправильно?

Ответы [ 5 ]

20 голосов
/ 10 марта 2011

Учитывая, что приведение не будет действительно проверять вещи, я бы пошел с полностью сырой версией:

if (cls.isEnum()){
    @SuppressWarnings("unchecked")
    Object val = Enum.valueOf(cls, "NAME1");
}

Это похоже на работу.Полный пример:

public class Test
{
    enum Foo
    {
        BAR, BAZ
    }


    public static void main(String[] args)
    {
        @SuppressWarnings("rawtypes")
        Class cls = Foo.class;

        if (cls.isEnum())
        {        
            @SuppressWarnings("unchecked")
            Object value = Enum.valueOf(cls, "BAR");
            System.out.println(value);
        }
    }
}
7 голосов
/ 10 марта 2011

Проблема в том, что у вас есть два ?, и они могут быть разными, и они должны быть одинаковыми.

Вы должны либо использовать неуниверсальный тип объявления универсального типа, такой как

public static <T extends Enum<T>> T val(Class<T> cls) {
    if(cls.isEnum()) { // is redundant when the compiler checks this.
        @SuppressWarnings("unchecked")
        Class<T> enumClass = (Class<T>) cls;
        T val = Enum.valueOf(enumClass, "NAME1");
        return val;
    }
    return null;
}

Однако вызов этого метода тоже немного кошмарный. ;)

4 голосов
/ 10 марта 2011

Class.getEnumConstants выдаст все перечисления, которые вы затем сможете найти интересующие вас.

Изменение кода Джона:

public class Test {
    private enum Foo {
        BAR, BAZ
    } 

    public static void main(String[] args) {
        Class<?> cls = Foo.class;

        if (cls.isEnum()) { 
            for (Object constant : cls.getEnumConstants()) { 
                Enum<?> enumConstant = (Enum<?>)constant;
                if (enumConstant.name().equals("BAR")) {
                    System.out.println(constant);
                    break;
                }
            }
        }
    }
}

В Java SE 8 вы, возможно, сможете сделать что-то умное с помощью лямбды и абстрактного потока управления.

Примечание:

  • Отражение - это почти всегда очень плохая идея.
  • Нет необходимости в непроверенном предупреждении или подавлении этих действительных предупреждений.
  • Нет необходимости в необработанных типах (которые когда-либо написаны и семантика) предупреждения или подавления этих действительных предупреждений.
  • Нет необходимости в необоснованной напыщенной речи.
  • Нет необходимости понижать этот ответ.
1 голос
/ 11 марта 2011

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

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

0 голосов
/ 27 февраля 2012
    class EnumValues<P extends Enum<P>>
    {
        public static <P extends Enum<P>> P [] getValues( Class<P> keyType)
        {
            return keyType.getEnumConstants();
        }
    }

Использование:

    Class cls = Thread.State.class;
    for( Enum en : EnumValues.getValues( cls)) 
        System.out.println( en.name()); 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...