Java 是否可以将两个通配符类型声明为同一类型?

Java 是否可以将两个通配符类型声明为同一类型?,java,generics,Java,Generics,我想创建一个从类类型到b的映射,从定义的类类型的对象的标识符到对象本身 我有以下资料: protected HashMap<Class<?>, HashMap<Long, ?>> obj = new HashMap<Class<?>, HashMap<Long, ?>>(); 您可以使用特定的泛型定义扩展HashMap类,并创建一个以作为参数的泛型类,如下所示: public class MyHashMap<T&g

我想创建一个从类类型到b的映射,从定义的类类型的对象的标识符到对象本身

我有以下资料:

 protected HashMap<Class<?>, HashMap<Long, ?>> obj = new HashMap<Class<?>, HashMap<Long, ?>>();
您可以使用特定的泛型定义扩展HashMap类,并创建一个以作为参数的泛型类,如下所示:

public class MyHashMap<T> extends HashMap<Class<T>, HashMap<Long, T>> { ...

作为替代方案,您可以使用少量非类型安全代码,这些代码以强制约束的方式封装:

class Cache {
    private Map<Class<?>, Map<Long, ?>> items = new HashMap<Class<?>, Map<Long, ?>>();

    private <T> Map<Long, T> getItems(Class<T> type) {
        @SuppressWarnings("unchecked")
        Map<Long, T> result = (Map<Long, T>) items.get(type);
        if (result == null) {
            result = new HashMap<Long, T>();
            items.put(type, result);
        }
        return (Map<Long, T>) result;
    }

    public <T> void addItem(Class<T> type, Long id, T item) {
        getItems(type).put(id, item);
    }

    public <T> T getItem(Class<T> type, Long id) {
        return type.cast(getItems(type).get(id));
    }
}

编译器不必抱怨getItem中的type.cast,但它有助于捕获早期进入缓存的错误类型的对象。

每次出现通配符都对应不同的类型,表示该类型的类型参数的唯一适当范围是外部HashMap中的条目。不幸的是,HashMap不允许在其类型参数中约束条目类型,如:

class Entry<K,V> {
    // fields omitted
}

class Map<E extends Entry<?,?> {

}

class EntityCacheEntry<E> extends Entry<Class<E>, Map<Entry<Long, E>>> { }

class EntityCache extends Map<EntityCacheEntry<?>> { }

您可能想要的是:HashMap您需要将该类型定义添加到使用HashMap的封闭类或方法中。我想我不能。我正在地图中收集/缓存一组类类型。不止一个。它可以是任何类型。还是我看错了?非常有趣的一点,但不幸的是,我不认为你可以建立这样的约束。你看错了。可以是任何类型,但所有出现的T都必须是相同的类型。通过使用原始定义和无界通配符,并使用强制约束的通用方法从映射中添加/检索项,可以实现大致相同的类型。这些代码不是类型安全的,但是封装良好的不安全代码可能是可以接受的。这不是OP所要求的。OP的要求是不可能的,为什么?如果他这样做,然后用新类型实例化他的对象,它将强制HashMap定义中的两个泛型类型相同,这是OP想要的。如果我理解正确,他希望映射包含如下内容:{Foo.class=>map,Bar.class=>map}是,你可以做到这一点:MyHashMap obj=新的MyHashMap将是一个扩展的HashMap。但是,根据OP对这个问题的评论,他希望映射键是不同类型的类对象。HashMap将完全无用,因为JVM中只有一个类型类实例。禁止使用在大多数应用程序中都不相关的类加载器。这是一个很好的解决方案,可以实现所有实际用途!谢谢这很有道理。对于外部世界来说,所有内容都是安全键入的。对于实现,使用了“安全强制转换”。顺便说一下,您提到了.cast是在将其放入缓存之前完成的。在您的代码片段中,您是在从缓存中检索后进行强制转换的。我真的很难理解为什么不等于。“?”不是“任何东西”的意思,它是一个对象吗?你想让我为这个做一个新的话题吗?你可能应该好好读一读。基本上,假设您有一个类型列表的引用;它可以指向List或List或List类型的对象。如果它是List类型的对象,则不能向其添加整数。换句话说,意味着有一些类型参数,因此所有元素都必须是该类型的,但我们不知道该类型参数是什么;所以我们不能安全地添加任何内容。另一方面,通过列表,您可以向其中添加任何内容。+1。谢谢你的回答。这与Ineradial的方法大致相同。
class Entry<K,V> {
    // fields omitted
}

class Map<E extends Entry<?,?> {

}

class EntityCacheEntry<E> extends Entry<Class<E>, Map<Entry<Long, E>>> { }

class EntityCache extends Map<EntityCacheEntry<?>> { }
class EntityCache {
    Map<Class<?>, Map<Long, Object>> map = new HashMap<>();

    public <E> void put(Class<E> clazz, long id, E entity) {
        map.get(clazz).put(id, entity);
        // TODO create map if it doesn't exist yet
    }

    public <E> E get(Class<E> clazz, long id) {
        return clazz.cast(map.get(clazz).get(id));
        // TODO what if not found?
    }
}