Java:特定的枚举和通用的Enum <! - ? - >参数

时间:2010-02-08 10:09:02

标签: java eclipse generics compiler-construction javac

我想将任何枚举值传递给实用程序类中的方法,并获取相同枚举类型的另一个枚举值。像这样:

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<?>参数有什么问题?

  3. 谢谢,

    Martin Schayna

2 个答案:

答案 0 :(得分:9)

  1. Eclipse编译器和javac有一些区别,特别是涉及泛型时。人们认为日食是正确的,但这并不重要:)

  2. 尝试

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

答案 1 :(得分: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数组中包含哪种类型的枚举。 / p>