使用Generic with Class <! - ? - >参数时出错

时间:2015-01-22 14:53:32

标签: java generics reflection enums

将Generic与Enum一起使用时遇到了一些问题:

enum MyEnum1 {
    // ...
    public static MyEnum fromString(String enumStr) { /* ... */ }
}

enum MyEnum2 {
    // ...
    public static MyEnum fromString(String enumStr) { /* ... */ }
}

enum MyEnum3 {
    // ...
    public static MyEnum fromString(String enumStr) { /* ... */ }
}

class MyClass {
    Map<Class<? extends Enum<?>, EnumSet<? extends Enum<?>>> map;

    public <E extends Enum<E>> void addValue2EnumSet(Class<E> enumType, E value);

    // enumType and valueStr is of the same length
    public static Map<Class<? extends Enum<?>, EnumSet<? extends Enum<?>>> getMapOfEnumSet(Class<? extends Enum<?>>[] enumTypes, String[] valueStrs) {
        MyClass c = // ...
        for (int i = 0; i < enumTypes.length; ++i) {
            // for each enumType and valueStr pair
            // add the value (= Enum1/2/3.fromString(valueStr)) to the Map
            Class<? extends Enum<?>> enumType = enumTypes[i];
            String valueStr = valueStrs[i];
            Method fromStringMethod = enumType.getDeclaredMethod("fromString", String.class);

            // error!
            c.addValue2EnumSet(enumType, enumType.cast(fromStringMethod.invoke(null, valueStr))); 
        }
        return c.map;
    }
}

在这一行c.addValue2EnumSet(enumType, enumType(fromStringMethod.invoke(null, valueStr)));中,编译错误是第二个参数Found: 'java.lang.Enum<?>,必需:'?扩展java.lang.Enum'`

如何在addValue2EnumSet()中致电getEnumSetOf()

在这种情况下,传递Class<? extends Enum<?> enumType参数,它用于判断哪种Enum(Enum1 / 2/3)是目标,然后调用fromString()方法生成相应的Enum实例。我不知道从enumType获取方法的反射。

困难的是getEnumSetOf的两个参数是数组,第一个参数中的每个元素,例如enumTypes[0],选择相应的第二个参数的枚举类型,例如{{1} }。也就是说,valueStrs[0]的目标类型是valueStrs[0]

1 个答案:

答案 0 :(得分:1)

不太确定为什么使用泛型 - 也许你可以进一步解释。

假设您想通过字符串名称从种子构建枚举集,您可能会发现此技术可用。其中关键部分是使用Enum.getDeclaringClass()方法。

enum ABEnum {

    A, B;

    public static ABEnum fromString(String enumStr) {
        return ABEnum.valueOf(enumStr);
    }
}

public static Enum fromString(Enum seed, String enumStr) throws Exception {
    Class declaringClass = seed.getDeclaringClass();
    Method fromStringMethod = declaringClass.getDeclaredMethod("fromString", String.class);
    Object result = fromStringMethod.invoke(null, enumStr);
    return (Enum) result;
}

public void test() throws Exception {
    Enum e = fromString(ABEnum.A, "B");
    System.out.println(e);
}

这似乎更适合您的场景 - 它通过反射构建一个与您的地图非常相似的地图。也许它会有所帮助。

enum ABEnum {

    A, B, E;

    public static ABEnum fromString(String enumStr) {
        return ABEnum.valueOf(enumStr);
    }
}

enum CDEnum {

    C, D, E;

    public static CDEnum fromString(String enumStr) {
        return CDEnum.valueOf(enumStr);
    }
}

public static Enum fromString(Enum seed, String enumStr) throws Exception {
    Class declaringClass = seed.getDeclaringClass();
    Method fromStringMethod = declaringClass.getDeclaredMethod("fromString", String.class);
    Object result;
    try {
        result = fromStringMethod.invoke(null, enumStr);
    } catch (InvocationTargetException e) {
        result = null;
    }
    return (Enum) result;
}

Map<Class, EnumSet> map = new HashMap<>();

public void test() throws Exception {
    //Enum e = fromString(ABEnum.A, "B");
    Enum[] enums = new Enum[]{ABEnum.A, CDEnum.C};
    String[] names = new String[]{"A", "B", "C", "D", "E"};
    for (Enum e : enums) {
        Class c = e.getClass();
        for (String s : names) {
            EnumSet set = map.get(c);
            if (set == null) {
                map.put(c, set = EnumSet.noneOf(c));
            }
            Enum found = fromString(e, s);
            if (found != null) {
                set.add(found);
            }
        }
    }
    System.out.println(map);
}