Проблемы при работе с картой<Class <?>, Object> в Java

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

member в MyClass используется для хранения нескольких видов EnumSet с различными типами Enum. При реализации относительных методов я сталкиваюсь с некоторыми проблемами: когда я пытаюсь вызвать метод следующим образом:

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

Как бороться с этой проблемой? Я думаю, что это может происходить из необработанного типа или стирания типа, но я не знаю основной причины. Благодарю.

2 ответа

Решение

Как бороться с этой проблемой?

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

Class объекты могут быть сложны в использовании. Как вы заметили, их нелегко использовать с общими типами, потому что из-за стирания типов EnumSet<Category>.class не является юридическим кодом Было бы невозможно использовать ваш подход к хранению EnumSetдля разных Enumпотому что есть только один Class объект для всех EnumSetс, а именно 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, вы обнаружите, что это не будет работать, потому что ключи не будут равны. Там нет никакого способа, чтобы написать equals() метод для ClassKey это работает, потому что из-за стирания типа было бы невозможно сказать ClassKey<EnumSet<Shape>> из ClassKey<EnumSet<Category>>,

Другие вопросы по тегам