将 Generic 与 Class<?> 参数一起使用时出错
Error when using Generic with Class<?> parameter
将泛型与枚举一起使用时遇到一些问题:
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'`
如何在getEnumSetOf()
中调用addValue2EnumSet()
?
此时传递了一个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);
}
这似乎更接近您的场景 - 它通过反射构建了一个与您的地图非常相似的地图。或许会有帮助。
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);
}
将泛型与枚举一起使用时遇到一些问题:
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'`
如何在getEnumSetOf()
中调用addValue2EnumSet()
?
此时传递了一个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);
}
这似乎更接近您的场景 - 它通过反射构建了一个与您的地图非常相似的地图。或许会有帮助。
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);
}