0
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 {
    // ...
};

memberinMyClass用于存储几种不同Enum 类型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);

}

错误来了:

putEnumSet(Class<E>, E)类型中的方法MyClass<Word>不适用于参数(Class<capture#1-of ? extends EnumSet>, EnumSet<Category>)

如何处理这个问题?我认为它可能来自raw typetype erasure,但我不知道主要原因。谢谢。

4

2 回答 2

1

如何处理这个问题?

E extends EnumSet<E>

这非常令人困惑,因为它说你必须有一个E必须扩展的元素,EnumSet<E>即你需要一个元素类型,它本身EnumSet就是E


您有一个问题,即所有 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));
    }
};
于 2014-12-28T10:17:01.010 回答
1

Class对象可能难以使用。正如您所注意到的,它们不容易与泛型类型一起使用,因为类型擦除EnumSet<Category>.class不是合法代码。不可能使用您的方法EnumSet为不同的 s 存储 s,因为所有Enums只有一个Class对象,即。 EnumSetEnumSet.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,您会发现它不起作用,因为键不相等。没有办法为此工作编写equals()方法ClassKey,因为由于类型擦除,不可能区分 aClassKey<EnumSet<Shape>>和 a ClassKey<EnumSet<Category>>

于 2014-12-28T10:40:14.083 回答