2010-02-08 108 views
6

我想將任何枚舉值傳遞給工具類中的方法,並獲得另一個枚舉類型相同的枚舉值。事情是這樣的:Java:特定枚舉和泛型枚舉<?>參數

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 

我在任的Eclipse和Maven使用Sun JDK 1.6

$ 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<?>參數有什麼問題?

感謝,

馬丁Schayna

+0

我刪除了maven-2標籤,因爲這不是maven相關的問題,而是純粹的eclipse/javac編譯器問題。 – 2010-02-08 17:30:17

+0

Eclipse擁有自己的編譯器,獨立於JDK。這就是爲什麼它不需要安裝JDK(您只需要JRE)。 – finnw 2010-02-08 17:32:13

回答

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 2010-02-08 10:46:13

+2

約束'>'是正確的,但是您可以使'T'(實際枚舉類型)爲返回類型,而不是'T'的抽象超類'Enum '。 – finnw 2010-02-08 10:47:56

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 2010-02-08 12:49:54