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

发布于 2024-11-24 18:34:30 字数 1632 浏览 0 评论 0 原文

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

在其他方法中,我想使用具有具体类型的值映射之一,但算法应该是通用的。我编写了 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>; IdentityMap = typeMap.get(type);
    • 编译器错误:类型不匹配:无法从 Map> 转换映射
  • 行中:typeMap.put(type, IdentityMap);
    • 编译器错误:类型 Map,Map> 类型中的 put(Class, Map>) 方法;>不适用于参数(Class、Map>)

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

Here is some code which does not compile. I would like to hold arbitrary pairs of Class<?> (key) and Map<Long, ObjectDescriptors<?>> (values) inside the typeMap;

From other methods I want to use one of the value maps with a concrete type, but the algorithms should be generic. I wrote the getIdentityMap() method to deliver a map with a concrete but generic type.

How must I modify the code to compile while being generic?

Thanks in advance.

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

EDIT: Here are the compiler errors:

  • In line: Map<Long, ObjectDescriptor<OBJECT_TYPE>> identityMap = typeMap.get(type);
    • compiler error: Type mismatch: cannot convert from Map<Long,ObjectDescriptor<Object>> to Map<Long,ObjectDescriptor<OBJECT_TYPE>>
  • In line: typeMap.put(type, identityMap);
    • compiler error: 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>>)

EDIT: edited the generic types of the map attribute to ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

孤云独去闲 2024-12-01 18:34:30

您无法使用“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 擦除了以保持与不使用泛型的旧类的兼容性。编译器从参数和参数中删除类型信息。

You cannot create generic instance with "T". Try using the "?"

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

As mentioned in the comments, this is because of Java erasure to maintain compatibility with older classes which did not use generics. The compiler removes the type information from parameters and arguments.

遥远的她 2024-12-01 18:34:30

如果您愿意重新设计一点并且可以接受单个未经检查的转换(在我看来,这永远不会失败),您就可以做到这一点。

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

}

You can do it if you are willing to re-design a bit and are OK with a single unchecked cast (which should never fail 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();
    }

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文