java泛型 - 确保工厂方法返回的对象与同一类型相关

时间:2012-02-21 10:27:49

标签: java generics

我有以下代码:

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类保证它们是相同的!

3 个答案:

答案 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();

但是你显然不会知道TS类型,所以你可以真正做到:

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()实现必须返回正确的实例,否则会导致运行时类转换异常。