【问题标题】:Java: Wildcard Types Mismatch Results in Compilation ErrorJava:通配符类型不匹配导致编译错误
【发布时间】:2013-11-01 22:20:17
【问题描述】:

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

以下代码是我正在使用的精简版。我尝试创建“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 的相关问题是:

【问题讨论】:

    标签: java generics wildcard


    【解决方案1】:

    使用以下内容:

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

    这只是编译器类型推断落空的一种情况,因此有必要为T显式提供类型参数。

    从技术上讲:

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

    同时,test3Manager 被声明为具有类型IManager&lt;IAnotherRandomType&lt;?&gt;&gt;,它有一个嵌套通配符 - 它的行为不像类型参数,而是表示任何类型.

    由于泛型aren't covariant,编译器无法从IManager&lt;IAnotherRandomType&lt;capture#1-of ?&gt;&gt; 转换为IManager&lt;IAnotherRandomType&lt;?&gt;&gt;

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

    【讨论】:

    • +1 只需进行一次编辑 - T 被推断为 IAnotherRandomType&lt;capture#1-of ?&gt;,而不仅仅是 capture#1-of ?
    • 协方差(没有)在这里真的相关吗? capture#1-of ?? 不相关吗?
    • @RohitJain 不错 - 已修复。
    • @mpartel 之所以相关,是因为IAnotherRandomType&lt;capture#1-of ?&gt;IAnotherRandomType&lt;?&gt; 的子类型。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多