Java泛型&不兼容的类型:编译器中的错误?

时间:2014-01-22 13:56:40

标签: java generics

我在stackoverflow中尚未讨论的条件中遇到“不兼容类型”编译器错误(例如Why won't this generic java code compile?)。

我的期望很简单 - 我正在调用一个模板化的方法,它不使用包含类的任何“泛型”类,因此它应该从方法参数中提取模板参数的类型,这应该在所有情况下编译 - 但我得到“不兼容的类型”编译器错误。

我注意到了修复问题的奇怪方法 - 在方法参数中将“<?extends Data> ”添加到通用数据类型。它如何改变编译器逻辑?

在我的理解中 - 应该没有区别,因为(1)DataContainer类的模板参数不用于方法调用,(2)限制“< TData extends Data> ”已定义最小基础对象类 - 数据 - 因此在编译没有参数的模板时应自动采用它。

public void processData(DataContainer<? extends Data> c) {

(可以使用显式类型转换,但我相信它在这里是多余的)

DummyContextClass dcc = (DummyContextClass)c.getContext(DummyContextClass.class);

复制/粘贴代码

public class Test {

    public static class Data {
    }

    public static class DataContainer<TData extends Data> {
        public final TData Data;
        private final Map<String, Object> contexts = new HashMap<>();

        public DataContainer(TData data) {
            Data = data;
        }

        public <T> T getContext(Class<T> type) {
            return (T)contexts.get(type.getName());
        }

        public <T> void setContext(Class<T> type, T context) {
            contexts.put(type.getName(), context);
        }
    }

    public static class DummyContextClass {
    }

    public void processData(DataContainer c) {
        c.setContext(DummyContextClass.class, new DummyContextClass());

        // error: incompatible types: Object cannot be converted to DummyContextClass
        DummyContextClass dcc = c.getContext(DummyContextClass.class);
    }
}

1 个答案:

答案 0 :(得分:6)

这个问题与你的通用方法没什么关系 您的问题是您使用原始类型作为方法的参数:

public void processData(DataContainer c) { // Oops! DataContainer is a raw type

您应该使用DataContainer的参数:

public void processData(DataContainer<? extends Data> c) {

当您不使用泛型类的类型时,您将拥有所谓的 raw 类型,并且(由于与旧Java版本的兼容性要求),将剥离所有通用信息课外。这(除其他外)将所有声明为泛型类型的返回类型更改为Object,因此出于编译目的,您的方法现在看起来像:

public Object getContext(Class type) {

...因此你的错误。