【问题标题】:Problems when operating on Map<Class<?>, Object> in Java在 Java 中对 Map<Class<?>, Object> 进行操作时出现问题
【发布时间】:2014-12-28 09:52:51
【问题描述】:
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用于存储不同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);

}

错误来了:

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

如何处理这个问题?我认为它可能来自原始类型类型擦除,但我不知道主要原因。谢谢。

【问题讨论】:

    标签: java generics type-erasure raw-types enumset


    【解决方案1】:

    如何处理这个问题?

    E extends EnumSet<E>
    

    这很令人困惑,因为它说你必须有一个元素 E 必须扩展 EnumSet&lt;E&gt; 即你需要一个元素类型,它本身就是 EnumSetE


    您有一个问题,即所有 EnumSet 类在运行时都相同。 IE。只有一个 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));
        }
    };
    

    【讨论】:

    • 哦,对了,类型擦除之后,所有的EnumSet都是同一个类型,EnumSet.class。使用元素类型作为键正是一个好主意。同时,请您解释一下错误(Class&lt;capture#1-of ? extends EnumSet&gt;, EnumSet&lt;Category&gt;),因为我仍然对此感到困惑?
    • @stanleyerror 令人困惑的部分是您的 E 类型必须扩展 EnumSet 即您有一个递归定义。
    • 最后Map&lt;Class&lt;?&gt;, Object&gt; member 就像:[String.class -&gt; Set&lt;String&gt;, Integer.class -&gt; Set&lt;Integer&gt;, ..., Enum1.class -&gt; EnumSet&lt;Enum1&gt;, Enum2.class -&gt; EnumSet&lt;Enum2&gt;, ...]。有没有办法判断memberkey 是否是Enum 的类?很抱歉再次打扰您。
    • @stanleyerror all enum 扩展类 Enum ,如果这就是你的意思。
    • @stanleyerror 你有很多不相关的问题。要测试一个键是否是enum 的成员,您可以检查if (key instanceof Enum) Enum1 的实例可以分配给Enum&lt;Enum1&gt;。类作为它的实例有不同的类型。 Class&lt;?&gt; 是一个未知类,它只允许不使用该类型的操作。 Class 将允许任何操作。
    【解决方案2】:

    Class 对象可能很难使用。正如您所注意到的,它们不容易与泛型类型一起使用,因为由于类型擦除,EnumSet&lt;Category&gt;.class 不是合法代码。不可能使用您的方法为不同的Enums 存储EnumSets,因为all EnumSets 只有一个Class 对象,即EnumSet.class

    我发现的一个解决方案是用我自己的密钥对象替换Class&lt;?&gt;。这是一个演示这种方法的完整程序。

    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&lt;EnumSet&lt;Shape&gt;&gt;EnumSet 放入member,然后尝试使用new ClassKey&lt;EnumSet&lt;Shape&gt;&gt; 检索EnumSet,您会发现它不会工作,因为密钥不相等。没有办法为ClassKey 编写一个有效的equals() 方法,因为由于类型擦除,不可能区分ClassKey&lt;EnumSet&lt;Shape&gt;&gt;ClassKey&lt;EnumSet&lt;Category&gt;&gt;

    【讨论】:

      猜你喜欢
      • 2021-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-12
      • 2011-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多