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

时间:2013-11-01 22:20:18

标签: 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;
            }
        }
    }

确切的编译错误消息是:

    Type mismatch: cannot convert from GenTest.IManager<GenTest.IAnotherRandomType<capture#1-of ?>> to GenTest.IManager<GenTest.IAnotherRandomType<?>>

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

关于SO的相关问题是:

1 个答案:

答案 0 :(得分:3)

使用以下内容:

IManager<IAnotherRandomType<?>> test3Manager =
        Factory.<IAnotherRandomType<?>>createManager(test3);

这只是编译器类型推断的一个例子,因此必须明确提供T的类型参数。

更专业:

声明

test3具有IAnotherRandomType<?>类型,其中?通配符捕获 - 一种表示的一次性类型参数一些特定的未知类型。这就是编译器在提到capture#1-of ?时所指的内容。当您将test3传递到createManager时,T会被推断为IAnotherRandomType<capture#1-of ?>

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

从泛型aren't covariant开始,编译器无法从IManager<IAnotherRandomType<capture#1-of ?>>转换为IManager<IAnotherRandomType<?>>

有关嵌套通配符的更多信息: