java - 将 Generic 与 Class<?> 参数一起使用时出错

标签 java generics reflection enums

将泛型与枚举一起使用时遇到一些问题:

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] ,选择第二个参数对应的Enum Type,例如valueStrs[0] 。也就是说valueStrs[0]的目标类型是 enumTypes[0] .

最佳答案

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

假设您希望通过字符串名称从种子构建枚举集,您可能会发现此技术可用。其中的关键部分是使用 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);
}

这似乎更接近您的场景 - 它通过反射构建了一个与您的 map 非常相似的 map 。也许会有帮助。

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);
}

关于java - 将 Generic 与 Class<?> 参数一起使用时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28091747/

相关文章:

java - 学习Java递归、阿克曼函数

c# - 致专家:此代码有何区别?

C# 具有相似类的泛型

java - 使用 Java 反射在集换式卡牌游戏中实现卡牌和效果

c# - 按仅在运行时已知的类型进行动态调度

java - 返回值反转

java - Peapod : Impl is not abstract and does not override abstract method start() in peapod. FramedVertexTraversal

java - 使用泛型创建类时出现 "> expected"错误

c# - 如何初始化对象属性

java - 如何解析文件中的数据行以填充每个数据行的对象?