2010-02-08 2 views
6

Я хочу передать любое значение enum методу в классе утилиты и получить другое значение перечисления того же типа перечисления. Что-то вроде этого:Java: специфические перечисления и общие параметры Enum <?>

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 в любом Затмении и 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<?>?

Спасибо,

Martin Schayna

+0

Я удалил тег maven-2, поскольку это не проблема, связанная с maven, а проблема компилятора чистого eclipse/javac. –

+0

Eclipse имеет собственный компилятор, независимый от JDK. Вот почему он не требует установки JDK (вам нужна только JRE.) – finnw

ответ

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

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

    public static <T extends Enum<T>> Enum<T> getEnumAttribute(Element element, String name, 
        Enum<T> defaultValue) { 
        ... 
    } 
    
+0

Спасибо, вы абсолютно правы, человек! С вашей альтернативной сигнатурой метода мой исходный код можно компилировать либо в Eclipse, либо в Maven. Я немного смущен различиями между обоими компиляторами ... Во всяком случае, еще раз спасибо! – mschayna

+2

Ограничение '>' правильно, но вы можете сделать тип T T (фактический тип перечисления) возвращаемым типом, а не 'Enum ', который является абстрактным суперклассом 'T'. – finnw

1

Я не знаю, какую версию 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.

+0

Благодарим вас за теоретический анализ, особенно «нежелательную» толерантность к двум различным типам перечислений (один для «defaultValue» и один для результата), но в моем случае это, вероятно, не вызовет много ошибок. Для полноты: Я использую Eclipse 3.5.1. – mschayna

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