Java: конкретные перечисления и общие параметры Enum <?> - PullRequest
6 голосов
/ 08 февраля 2010

Я хочу передать любое значение перечисления методу в служебном классе и получить другое значение перечисления того же типа перечисления. Примерно так:

public class XMLUtils {

    public static Enum<?> getEnumAttribute(Element element, String name, 
            Enum<?> defaultValue) {

        if (element.hasAttribute(name)) {
            String valueName = element.getAttribute(name);
            // search for value 
            for (Enum<?> value: defaultValue.getClass().getEnumConstants())
                if (value.toString().equalsIgnoreCase(valueName))
                    return value;
        }
        // not found, return default value
        return defaultValue;
    } 
}

Использование метода getEnumAttribute():

// simple enum
public enum EUploadMethod {
    INSERT, UPDATE, DELETE
}

// read enum value from XML config file
EUploadMethod method = XMLUtils.getEnumAttribute(element, "method",
        EUploadMethod.INSERT);

Этот код полностью функционален, Eclipse компилирует и запускает его без предупреждений или ошибок, и он работает как чудо.

Но когда я очищаю и компилирую проект из командной строки от Maven2, он завершается ошибкой в строке, где getEnumAttribute вызывается:

$ mvn clean compile
....
[ERROR] /home/.... DataUploader.java:[173,53] inconvertible types
found   : java.lang.Enum<capture#414 of ?>
required: .....DataUploader.EUploadMethod

Я использую Sun JDK 1.6 в Eclipse и Maven:

$ mvn -version
Apache Maven 2.2.1 (r801777; 2009-08-06 21:16:01+0200)
Java version: 1.6.0_14
Java home: /usr/lib/jvm/java-6-sun-1.6.0.14/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "linux" version: "2.6.27-17-generic" arch: "i386" Family: "unix"

Вопросы:

  1. Почему этот код компилируется и функционирует в Eclipse , а компиляция завершается неудачно в Maven , который использует, насколько мне известно, тот же компилятор javac?

  2. Что не так с передачей определенных перечислений в общие Enum<?> параметры?

Спасибо

Мартин Шайна

Ответы [ 2 ]

9 голосов
/ 08 февраля 2010
  1. Компилятор Eclipse и javac имеют некоторые различия, особенно когда дело касается дженериков. Считается, что затмение правильно, но это не имеет значения:)

  2. Попробуйте

    public static <T extends Enum<T>> Enum<T> getEnumAttribute(Element element, String name, 
        Enum<T> defaultValue) {
       ...
    }
    
1 голос
/ 08 февраля 2010

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

Проблема в том, что у вас есть две маски ("?") в сигнатуре getEnumAttribute(), но нет никаких ограничений (и их невозможно создать), которые заставляют их быть одинаковыми. Таким образом, клиент может передать перечисление одного типа в качестве значения по умолчанию и получить перечисление другого типа в ответ.

Вы можете устранить ошибку в вызывающем коде, заменив обе подстановочные знаки параметром именованного типа:

class XMLUtils {

    @SuppressWarnings("unchecked")
    public static <E extends Enum<E>> E getEnumAttribute(Element element, String name, 
            E defaultValue) {

        if (element.hasAttribute(name)) {
            String valueName = element.getAttribute(name);
            // search for value 
            for (Enum<?> value: defaultValue.getClass().getEnumConstants())
                if (value.toString().equalsIgnoreCase(valueName))
                    return (E) value;
        }
        // not found, return default value
        return defaultValue;
    } 
}

Но я не думаю, что можно исключить непроверенное приведение, потому что Enum<E>.getClass() возвращает Class<Enum<?>>, поэтому компилятор не может определить, какой тип перечисления содержится в массиве enumConstants.

...