2010-02-08 154 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