我有以下代码:
interface Factory<T extends A<S>, S extends B> {
T getA();
S getB();
}
...
interface A<T extends B> {
void doB(T b);
}
...
interface B { }
现在我要做的是一个方法getFactory,它返回任意Factory-ies。 Factory类型参数确保(据我所知)我可以调用
Factory<?????> factory = getFactory();
factory.getA().doB(factory.getB());
但我无法获得正确的类型参数。它可能吗?
我试过
Factory<? extends A<? extends B>, ? extends B> factory = getFactory();
但是呢?延伸B和? extends B是两个不同的东西,即使Factory类保证它们是相同的!
答案 0 :(得分:4)
首先,让我稍微澄清一下您的示例代码。让它像这样:
interface Factory<SpecificHandler extends Handler<SpecificMessage>, SpecificMessage extends Message> {
SpecificHandler getHandler();
SpecificMessage getMessage();
}
interface Handler<T extends Message> {
void handle(T b);
}
interface Message { }
因此,您有一个工厂,可以为该特定消息生成消息和处理程序。以下代码不起作用,因为编译器太懒而无法检查,处理程序和消息都来自同一个工厂:
Factory<? extends Handler<?>, ? extends Message> factory = getFactory();
Handler<? extends Message> handler = factory.getHandler();
Message message = factory.getMessage();
handler.handle(message);//error
要解决此问题,必须将类型参数绑定到相同的实际类型。但你不知道确切的类型。 我能想象的唯一可能的解决方案:
<T extends Message> void doWork() {
Factory<? extends Handler<T>, T> x = getFactory();
Handler<T> handler = x.getHandler();
T message = x.getMessage();
handler.handle(message);
}
void test() {
doWork();
}
这里我们向方法签名引入一个无意义的类型参数T,只是为了将handler和factory绑定到同一个消息类型。
答案 1 :(得分:0)
如果getFactory()
返回工厂,则S扩展B&gt;你不知道A或B你可以使用:
Factory<?, ?> factory = getFactory();
但是你显然不会知道T
和S
类型,所以你可以真正做到:
Factory factory = getFactory();
你也可以使用:
Factory<A<B>, B> factory = getFactory();
然后你会知道Factory方法的返回类型分别为A和B.
答案 2 :(得分:0)
如果你想拥有可以使用各种模板返回对象的工厂方法,我建议将getFactory
声明为通用方法,如此
public <T extends A<S>, S extends B> Factory<T, S> getFactory() {
然后你可以这样称呼它:
Factory<MyClass1, MyClass2> someFact = getFactory();
如果这些事情成立:
MyClass1
扩展A<MyClass2>
MyClass2
扩展B
当然getFactory()
实现必须返回正确的实例,否则会导致运行时类转换异常。