将枚举常量名称转换回枚举常量的通用方法

4
以下名为reverse的方法,将如何重写为允许任何枚举类型的通用方法?
public class TestX {

    enum Gender { male, female }

    public static void main(String[] args) {
        System.out.printf("%s\n", TestX.reverse("male").name());
        System.out.printf("%s\n", TestX.reverse("female").name());
    }

    static Gender reverse(String name) {
        for (Gender g: Gender.class.getEnumConstants())
            if (g.name().equals(name))
                return g;
        return null;
    }
}

我尝试了以下代码(但无法在T.class编译):

<T extends Enum<?>> T reverse2(String name) {
     for (T t: T.class.getEnumConstants())
         if (t.name().equals(name)) return t; 
     return null; 
}

你尝试过这样重写它吗? - nanofarad
是的,我已经尝试过了。如果没有答案,我很快就会发布我的尝试。 - H2ONaCl
1
最好将其发布,这样我们就知道您需要什么帮助以及答案中需要关注什么。 - nanofarad
1
T.class是泛型无法实现的一件事情,因为相同的字节码适用于每个T。显式传递Class<T>是常见的解决方法,如Steve P.的回答中所示。 - Alan Stokes
2个回答

6
如何呢?
// Every enum class extends Enum<ThisEnumClassName>. 
// Since we want T to be enum we must write it as "extends Enum"
// but Enum is also generic and require type of store parameters 
// so we need to describe it as Enum<T> which finally gives us - T extends Enum<T>
static <T extends Enum<T>> T reverse(String name, Class<T> clazz) {
    for (T t : clazz.getEnumConstants())
        if (t.name().equals(name))
            return t;
    return null;
}

如果您想要通用化,您需要指定从哪个枚举中获取您的值。否则,没有办法找到正确的枚举(除非您还在name中放置了它,例如full.package.name.of.YourEnum.VALUE)。
您也可以考虑使用
Enum.valueOf(YourEnumClass.clazz, "ENUM_FIELD_NAME")

但是这种方法在枚举没有指定元素时,不会返回null,而是会抛出java.lang.IllegalArgumentException异常。


2
我相信以下内容可以解决问题:
static <T extends Enum<T>> T reverse(String name, Class<T> t_class) {
    for (T t: t_class.getEnumConstants())
           if (t.name().equals(name))
                 return t;

    return null;
}

我认为 <T extends Enum<T>> 是一个循环定义。 - H2ONaCl
3
不,不是这样的。考虑:需要一个泛型对象列表,并且这些对象彼此之间是可比较的,因此您需要 <T extends Comparable<T>> - Steve P.
1
@broiyan:不是的。所有枚举类型都继承自泛型类java.lang.Enum。当你写public enum MyEnum时,MyEnum就成为了Enum<MyEnum>的简写形式。因此,为了编写一个有界类型参数的泛型方法,该方法接受一个枚举类型,public <T extends Enum<T>> void myMethod() {...}正是所需的。 - scottb
1
这个可以在不使用异常捕获的情况下工作。由于T是一个Enum<>,所以name()调用不应该抛出异常。 - H2ONaCl
@broiyan 好的,说得对。我忘记了那件事。 - Steve P.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接