如何将泛型与类型参数和通配符一起使用?

时间:2011-07-16 12:01:26

标签: java generics map wildcard

这是一些无法编译的代码。我想在typeMap中保留Class<?>(键)和Map<Long, ObjectDescriptors<?>>(值)的任意对;

从其他方法我想使用具有具体类型的值映射之一,但算法应该是通用的。我编写了getIdentityMap()方法来提供具有通用类型的地图。

如何在通用时修改要编译的代码?

提前致谢。

    private final Map<Class<?>, Map<Long, ObjectDescriptor<?>>> typeMap = new HashMap<Class<?>, Map<Long,ObjectDescriptor<?>>();

private <T> Map<Long, ObjectDescriptor<T>> getIdentityMap(Class<T> type) {
    Map<Long, ObjectDescriptor<T>> identityMap = typeMap.get(type);
    if (identityMap == null) {
        identityMap = new HashMap<Long, ObjectDescriptor<T>>();
        typeMap.put(type, identityMap);
    }
    return identityMap;
}

编辑:以下是编译器错误:

  • 排队:Map<Long, ObjectDescriptor<OBJECT_TYPE>> identityMap = typeMap.get(type);
    • 编译错误:Type mismatch: cannot convert from Map<Long,ObjectDescriptor<Object>> to Map<Long,ObjectDescriptor<OBJECT_TYPE>>
  • 排队:typeMap.put(type, identityMap);
    • 编译错误:The method put(Class<?>, Map<Long,ObjectDescriptor<Object>>) in the type Map<Class<?>,Map<Long,ObjectDescriptor<Object>>> is not applicable for the arguments (Class<OBJECT_TYPE>, Map<Long,ObjectDescriptor<OBJECT_TYPE>>)

编辑:将地图属性的通用类型编辑为?

2 个答案:

答案 0 :(得分:1)

您无法使用“T”创建通用实例。尝试使用“?”

 private final Map<Class<?>, Map<Long, ObjectDescriptor<?>>> typeMap = new HashMap<Class<?>, Map<Long,ObjectDescriptor<?>>>();


private <T> Map<Long, ObjectDescriptor<?>> getIdentityMap(Class<?> type) {
    Map<Long, ObjectDescriptor<?>> identityMap = typeMap.get(type);
    if (identityMap == null) {
        identityMap = new HashMap<Long, ObjectDescriptor<?>>();
        typeMap.put(type, identityMap);
    }
    return identityMap;
}

正如评论中所提到的,这是因为Java擦除以保持与不使用泛型的旧类的兼容性。编译器从参数和参数中删除类型信息。

答案 1 :(得分:1)

如果您愿意重新设计一下并且可以使用单个未经检查的演员(IMO绝对不会失败),您可以这样做。

public class TmpTest {

    public static void main(final String[] args) {
        ClassDescriptorMap m = new ClassDescriptorMap();

        LongDescriptorMap<String> identityMap = m.getIdentityMap(String.class);
        identityMap.put(1L, Arrays.asList("hi"));
        System.out.println(identityMap);
        identityMap = m.getIdentityMap(String.class);
        identityMap.put(2L, Arrays.asList("hello"));
        System.out.println(identityMap);

        LongDescriptorMap<Object> identityMap2 = m.getIdentityMap(Object.class);
        System.out.println(identityMap2);
    }

}

class ClassDescriptorMap {

     private final Map<Class<?>, LongDescriptorMap<?>> typeMap = new HashMap<Class<?>, LongDescriptorMap<?>>();

     public <T> LongDescriptorMap<T> getIdentityMap(Class<T> type) {
         @SuppressWarnings("unchecked")
        LongDescriptorMap<T> identityMap = LongDescriptorMap.class.cast(typeMap.get(type));
         if (identityMap == null) {
             identityMap = new LongDescriptorMap<T>();
             typeMap.put(type, identityMap);
         }
         return identityMap;
     }

     @Override
     public String toString() {
         return typeMap.toString();
     }
}

class LongDescriptorMap<T> {

    private Map<Long, List<T>> map = new HashMap<Long, List<T>>();

    public List<T> get(Object key) {
        return map.get(key);
    }

    public List<T> put(Long key, List<T> value) {
        return map.put(key, value);
    }

    @Override
    public String toString() {
        return map.toString();
    }

}