我在我的项目中创建了一个工厂类,它允许我(理论上)为任何(支持的)给定类型创建管理器。与管理器交互允许我改变给定类型的某些属性。我面临的问题是当我尝试为泛型类型创建一个管理器时,编译器会破坏我的希望和梦想。
以下代码是我正在使用的精简版本。我尝试创建'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的相关问题是:
答案 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<?>>
。
有关嵌套通配符的更多信息: