【问题标题】:Class implementing an interface is not accepted for generics wildcard泛型通配符不接受实现接口的类
【发布时间】:2020-04-07 10:48:37
【问题描述】:

我想要一个将类类型作为键的映射,以避免在访问值时进行强制转换。

更新
以下是您可以在 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());  

错误:

第二个参数类型错误。发现:“需要一些具体的类”?延伸 我的界面`

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

【问题讨论】:

  • 请发布一个实际的非工作示例;您省略了一些重要的细节,例如访问修饰符和类结构。
  • @chrylis-onstrike- 这是一个实际的非工作示例,刚刚对其进行了测试,Idea 告诉我需要类型:捕获?扩展 MyInterface 提供:SomeConcreteClass
  • @chrylis-onstrike-:帖子中的代码,如果您将其复制/粘贴到 IDEA 中,您可以重现该问题。谢谢Artsiom

标签: java generics


【解决方案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);
}

【讨论】:

  • 这确实很有帮助。顺便说一句,我在那里尝试做的事情有解决方案吗? IE。避免演员表?
  • @Jim 我真的想问你,为什么你认为你需要? extends MyInterface 部分?你知道你可以把它声明为private Map&lt;Class&lt;?&gt;, MyInterface&gt; map = ...,对吧?在Map 声明中引入有界类型的实际好处是什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多