让我们假设两个接口(interface):

public interface FruitHandler<T extends Fruit>
{
    setFruit(T fruit);
    T getFruit();
}

public interface Fruit
{
}

现在我想要一个工厂来创建FruitHandlers(例如AppleHanderOrangeHandler,...),但是FruitHandlerFactory不知道两个接口(interface)的实现类都是必需的(例如java parameterized generic static factory中)。 FruitHandlerFactory应该以这种方式工作(OrangeHandler实现FruitHandler,而Orange实现Fruit):
FruitHandlerFactory fhf = new FruitHandlerFactory<OrangeHandler,Orange>();
OrangeHandler fh = fhf.create();
Orange orange = (Orange)fh.getFruit();

这应该是工厂:
public class FruitHandlerFactory<A extends FruitHandler, B extends Fruit>
{
    public FruitHandler create()
    {
        FruitHandler<Fruit> fh = new A<B>();   //<--- ERROR
        fh.setFruit(new B());
        return fh;
    }
}

我收到此错误的地方:
The type A is not generic; it cannot be parameterized with arguments <B>

顺便说一句:是否可以使create()方法为静态方法?

最佳答案

由于Java中的泛型使用擦除来实现,因此FruitHandlerFactory的类型信息在运行时将不可用,这意味着您无法以这种方式实例化A(或B)。

但是,您可以传入正确类型的Class对象来解决此问题:

public class FruitHandlerFactory<H extends FruitHandler<F>, F extends Fruit> {
    final Class<H> handlerClass;
    final Class<F> fruitClass;

    public FruitHandlerFactory(final Class<H> handlerClass, final Class<F> fruitClass) {
        this.handlerClass = handlerClass;
        this.fruitClass = fruitClass;
    }

    public H create() throws InstantiationException, IllegalAccessException {
        H handler = handlerClass.newInstance();
        handler.setFruit(fruitClass.newInstance());
        return handler;
    }
}

一个较小的缺点是,如果要实例化FruitHandlerFactory,则必须将类型名称写三遍(1):
FruitHandlerFactory fhf = new FruitHandlerFactory<OrangeHandler,Orange>(OrangeHandler.class, Orange.class);

您可以通过在static上生成createFactory() FruitHandlerFactory方法来稍微减少这种情况:
static <H extends FruitHandler<F>, F extends Fruit> FruitHandlerFactory<H, F> createFactory(
        final Class<H> handlerClass, final Class<F> fruitClass) {
    return new FruitHandlerFactory<H, F>(handlerClass, fruitClass);
}

并像这样使用它:
FruitHandlerFactory fhf = FruitHandlerFactory.createFactory(OrangeHandler.class, Orange.class);

10-08 01:11