Java:通配符类型不匹配导致编译错误

jdk*_*ght 5 java generics wildcard

我在我的项目中创建了一个工厂类,它允许我(理论上)为任何(支持的)给定类型创建管理器.与管理器交互允许我改变给定类型的某些属性.我面临的问题是当我尝试为泛型类型创建一个管理器时,编译器会破坏我的希望和梦想.

以下代码是我正在使用的精简版本.我尝试创建'test3Manager'的行不会编译,我试图理解为什么会这样.它下面的行显示了一个'解决方法',我试图避免.

    import java.util.List;

    public class GenTest {
        public static void main(String[] args) {
            String test1 = "";
            IRandomType<String> test2 = null;
            IAnotherRandomType<?> test3 = null;

            IManager<String> test1Manager = Factory.createManager(test1);
            IManager<IRandomType<String>> test2Manager = Factory.createManager(test2);
            IManager<IAnotherRandomType<?>> test3Manager = Factory.createManager(test3); // Doesn't compile. Why?

            // Work around?
            IManager<?> test3ManagerTmp = Factory.createManager(test3);
            IManager<IAnotherRandomType<?>> test3Manager2 = (IManager<IAnotherRandomType<?>>) test3ManagerTmp;
        }

        public interface IRandomType<T> {}
        public interface IAnotherRandomType<T> {}
        public interface IManager<T> {}

        public static class Factory {
            public static <T> IManager<T> createManager(T object) {
                return null;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

确切的编译错误消息是:

    Type mismatch: cannot convert from GenTest.IManager<GenTest.IAnotherRandomType<capture#1-of ?>> to GenTest.IManager<GenTest.IAnotherRandomType<?>>
Run Code Online (Sandbox Code Playgroud)

之前已经提出了类似的问题(见下文); 但是,我不知道这个问题是否与他们重复.我只是陈述这一点,因为我无法从这些问题中推断出我的答案.我希望有人可以澄清我使用仿制药时我做错了什么.

关于SO的相关问题是:

Pau*_*ora 4

使用以下内容:

IManager<IAnotherRandomType<?>> test3Manager =
        Factory.<IAnotherRandomType<?>>createManager(test3);
Run Code Online (Sandbox Code Playgroud)

这只是编译器类型推断失败的一个例子,因此有必要显式提供 的类型参数T

更技术性地说:

test3被声明为具有类型IAnotherRandomType<?>,其中?通配符捕获- 一种表示某些特定未知类型的一次性类型参数。这就是编译器所说的capture#1-of ?。当你传入test3,createManagerT推断为IAnotherRandomType<capture#1-of ?>

同时,被声明为具有嵌套通配符的test3Manager类型- 它的行为不像类型参数,而是代表任何类型IManager<IAnotherRandomType<?>>

由于泛型不是协变的,编译器无法从 转换IManager<IAnotherRandomType<capture#1-of ?>>IManager<IAnotherRandomType<?>>

有关嵌套通配符的更多阅读: