在 Java 中的 Map<Class<?>、Object> 上操作时出现的问题


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即你需要一个元素类型,它本身就是EEnumSet


您遇到的问题是所有 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不是合法代码。不可能使用您的方法来存储不同EnumEnumSet,因为所有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>>

相关内容

  • 没有找到相关文章

最新更新