有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

泛型通配符不接受实现接口的java类

我希望使用类类型作为键的映射,以避免在访问值时强制转换

更新
下面是您可以复制/粘贴到IDEA中并复制它的实际代码

    interface MyInterface {

    }

    class SomeConcreteClass implements MyInterface{

    }

    private Map<Class<?>, ? extends MyInterface> map = newMap();

    private Map<Class<?>, ? extends MyInterface> newMap() {
        Map<Class<?>, ? extends MyInterface> map = new HashMap<>();
        map.put(SomeConcreteClass.class, new SomeConcreteClass());
        return map;
    }

    private void accessMap() {
        SomeConcreteClass clazz = (SomeConcreteClass) map.get(SomeConcreteClass.class); <== I want to avoid cast here
    }

问题:这无法编译。我排在这一行:

map.put(SomeConcreteClass.class, new SomeConcreteClass());  

错误:

Wrong 2nd argument type. Found: 'SomeConcreteClass required '? extends MyInterface`

我做错了什么SomeConcreteClass应该被接受,因为它实现了接口


共 (1) 个答案

  1. # 1 楼答案

    这可以简化很多:

    Map<String, ? extends CharSequence> map = new HashMap<>();
    map.put("", ""); // <  will not compile
    
    List<? extends CharSequence> l = new ArrayList<>();
    l.add(""); // <  will not compile
    

    这背后的原理被称为PECS非常著名)。不允许这样做的原因读起来有点冗长,但主要是解释了here。虽然不明显,但如果允许的话——这可能会在其他地方造成问题,我链接的答案解释了这一点

    您可以通过所谓的typesafe heterogeneous container实现您想要的:

    static class TypeSafeValue {
    
        private MyInterface t;
    
        TypeSafeValue() {
        }
    
        public <T> TypeSafeValue setValue(MyInterface t) {
            this.t = t;
            return this;
        }
    
        public <T> T getValue(Class<T> clazz) {
            return clazz.cast(t);
        }
    }
    

    其用途是:

    private Map<Class<?>, TypeSafeValue> newMap() {
        Map<Class<?>, TypeSafeValue> map = new HashMap<>();
        map.put(SomeConcreteClass.class, new TypeSafeValue().setValue(new SomeConcreteClass()));
        return map;
    }
    
    private void accessMap() {
        SomeConcreteClass clazz = map.get(SomeConcreteClass.class).getValue(SomeConcreteClass.class);
    }