java - 使用相同的参数类型创建通用映射来保存类型的键和值

标签 java generics

我有一个由两个类实现的接口(interface)

interface I {}
class A implements I {}
class B implements I {}

现在我想创建一个映射,它可以将键作为使用 I 实现的任何对象的类,并将值作为该类的对象。这样我就可以做到这一点:

map.put(A.class, new A());
map.put(B.class, new B());

以下所有情况都应该给出错误:

map.put(A.class, new B());
map.put(I.class, new B());

以下 map 这样无效:

Map<Class<? extends I>, ? extends I> map;

因为第一次捕获与第二次捕获不同。如何获得所需的 map ?

最佳答案

怎么样

interface I {
}

class A implements I {
}

class B implements I {
}

public class Example {
    public static <T extends I, M extends Map<Class<T>, T>> void put(M map, Class<T> key, T value) {
        map.put(key, value);
    }

    public static void main(String[] args) {
        Map map = new HashMap<Class<I>, I>();
        put(map, A.class, new A());
        put(map, A.class, new B());  // error
        put(map, B.class, new A());  // error
        put(map, B.class, new B());
    }
}

如果您不介意在运行时出现错误,您可以这样做:

interface I {
}

class A implements I {
}

class B implements I {
}

public class MyMap implements Map<Class<? extends I>, I> {
    private final Map<Class<? extends I>, I> map;

    public MyMap(Map<Class<? extends I>, I> map) {
        this.map = map;
    }

    public int size() {
        return map.size();
    }

    public boolean isEmpty() {
        return map.isEmpty();
    }

    public boolean containsKey(Object key) {
        return map.containsKey(key);
    }

    public boolean containsValue(Object value) {
        return map.containsValue(value);
    }

    public I get(Object key) {
        return map.get(key);
    }

    public I put(Class<? extends I> key, I value) {
        assert key.getClass().isAssignableFrom(value.getClass());
        return map.put(key, value);
    }

    public I remove(Object key) {
        return map.remove(key);
    }

    public void putAll(Map<? extends Class<? extends I>, ? extends I> m) {
        map.putAll(m);
    }

    public void clear() {
        map.clear();
    }

    public Set<Class<? extends I>> keySet() {
        return map.keySet();
    }

    public Collection<I> values() {
        return map.values();
    }

    public Set<Entry<Class<? extends I>, I>> entrySet() {
        return map.entrySet();
    }

    public static void main(String[] args) {
        MyMap map = new MyMap(new HashMap<Class<? extends I>, I>());
        map.put(A.class, new A());
        map.put(A.class, new B());  // runtime error
        map.put(B.class, new A());  // runtime error
        map.put(B.class, new B());
    }
}

如果 map 实现 Map,就不可能出现这样的编译时错误:

    put(map, A.class, new A());
    put(map, A.class, new B());  // error
    put(map, B.class, new A());  // error
    put(map, B.class, new B());

这是因为无法使用 Map 接口(interface)将 V 指定为依赖于 K。您必须向客户提供一个具有运行时错误并实现 Map 的类,或者一个具有编译时错误且未实现 Map 的类。

关于java - 使用相同的参数类型创建通用映射来保存类型的键和值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33008550/

相关文章:

java - 如何在 java 中创建 docx4j 对象列表?

java - Swing - 访问时不可见的列抛出异常

java - 调试时空指针(java.io.File)异常消失

c# - 我可以使用泛型来推断已知类型的实际类型吗?

asp.net-mvc - viewdata 中的 ASP.NET MVC 通用列表

generics - 迅速 : How to write generic function that calls specialized ones

c# - 使用 System.Object 时实现对泛型方法的 new() 约束

java - 直接在PagerAdapter中获取上下文?

java - 不确定为什么会发生越界异常

c# - 使用 List<T> 参数构造 HashSet<T> 时是否允许重复?