public class MyClass<T> {
private Map<Class<?>, Object> member;
public <E> void putEnumSet(Class<E> enumSetType, E enumSet) {
this.member.put(enumSetType, enumSetType.cast(enumSet));
}
public <E> E getEnumSet(Class<E> enumType) {
return enumType.cast(this.member.get(enumType));
}
};
public enum Category {
// ...
};
MyClass
中的member
用于存储几种具有不同枚举类型的EnumSet。在实现相对方法时,我遇到了一些问题:当我尝试像这样调用该方法时:
public static void main(String[] args) {
EnumSet<Category> set = EnumSet.noneOf(Category.class);
MyClass<Word> newClass = new MyClass<Word>();
newClass.putEnumSet(set.getClass(), set);
}
错误来了:
类型
MyClass<Word>
中putEnumSet(Class<E>, E)
的方法不适用于参数(Class<capture#1-of ? extends EnumSet>, EnumSet<Category>)
如何处理这个问题?我认为它可能来自原始类型或类型擦除,但我不知道主要原因。谢谢。
如何处理这个问题?
E extends EnumSet<E>
这是非常令人困惑的,因为它说你必须有一个必须扩展EnumSet<E>
的元素E
即你需要一个元素类型,它本身就是E
的EnumSet
您遇到的问题是所有 EnumSet 类在运行时都相同。 也就是说,只有一个 EnumSet.class。 您最好记录元素的类。
public class MyClass {
private Map<Class, Set> member;
public <E> void putEnumSet(Class<E> elementType, Set<E> enumSet) {
this.member.put(elementType, enumSet);
}
public <E> Set<E> getEnumSet(Class<E> elementType) {
return (Set<E>) this.member.get(elementType));
}
};
Class
对象可能难以使用。正如您所注意到的,它们不容易与泛型类型一起使用,因为由于类型擦除EnumSet<Category>.class
不是合法代码。不可能使用您的方法来存储不同Enum
的EnumSet
,因为所有EnumSet
只有一个Class
对象,即 EnumSet.class
。
发现的一个解决方案是用我自己的密钥对象替换Class<?>
。下面是演示此方法的完整程序。
public class Main {
public enum Shape { SQUARE, CIRCLE, TRIANGLE }
// Here you would instantiate all the keys you will need.
public static final ClassKey<String> STRING_KEY = new ClassKey<String>();
public static final ClassKey<EnumSet<Shape>> SHAPE_SET_KEY = new ClassKey<EnumSet<Shape>>();
public static final class ClassKey<T> { private ClassKey() {} }
private Map<ClassKey<?>, Object> member = new HashMap<ClassKey<?>, Object>();
public <E extends Enum<E>> void putEnumSet(ClassKey<EnumSet<E>> enumSetType, EnumSet<E> enumSet) {
this.member.put(enumSetType, enumSet);
}
public <E extends Enum<E>> EnumSet<E> getEnumSet(ClassKey<EnumSet<E>> enumType) {
return (EnumSet<E>) member.get(enumType);
}
public static void main(String[] args) {
Main main = new Main();
EnumSet<Shape> enumSet = EnumSet.allOf(Shape.class);
main.putEnumSet(SHAPE_SET_KEY, enumSet);
EnumSet<Shape> shapes = main.getEnumSet(SHAPE_SET_KEY);
System.out.println(shapes);
}
}
这种方法的一个主要缺点是您必须有一个固定的ClassKey
对象库。动态创建这些对象是行不通的,因为如果您使用 new ClassKey<EnumSet<Shape>>
将EnumSet
放入member
,然后尝试使用 new ClassKey<EnumSet<Shape>>
检索EnumSet
,您会发现它不起作用,因为键将不相等。没有办法为ClassKey
编写有效的equals()
方法,因为由于类型擦除,无法区分ClassKey<EnumSet<Shape>>
和ClassKey<EnumSet<Category>>
。