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

Xtr*_*der 0 java generics

我在堆栈溢出中尚未讨论的条件中遇到"不兼容类型"编译器错误(例如,为什么这个通用java代码不会编译?).

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

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

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

public void processData(DataContainer<? extends Data> c) {
Run Code Online (Sandbox Code Playgroud)

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

DummyContextClass dcc = (DummyContextClass)c.getContext(DummyContextClass.class);
Run Code Online (Sandbox Code Playgroud)

复制/粘贴代码

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

Boh*_*ian 6

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

public void processData(DataContainer c) { // Oops! DataContainer is a raw type
Run Code Online (Sandbox Code Playgroud)

你应该使用一个参数DataContainer:

public void processData(DataContainer<? extends Data> c) {
Run Code Online (Sandbox Code Playgroud)

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

public Object getContext(Class type) {
Run Code Online (Sandbox Code Playgroud)

...因此你的错误.