具有未知实现类的通用工厂

Tho*_*hor 35 java generics

我们假设有两个接口:

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

public interface Fruit
{
}
Run Code Online (Sandbox Code Playgroud)

现在我想要一个工厂来创建FruitHandlers(例如AppleHander,OrangeHandler...),但是FruitHandlerFactory不知道两个接口的实现类的必要性(比如在java参数化的通用静态工厂中).本FruitHandlerFactory应以这种方式工作(其中OrangeHandler农具FruitHandlerOrange工具Fruit):

FruitHandlerFactory fhf = new FruitHandlerFactory<OrangeHandler,Orange>();
OrangeHandler fh = fhf.create();
Orange orange = (Orange)fh.getFruit();
Run Code Online (Sandbox Code Playgroud)

这应该是工厂:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我收到此错误的地方:

The type A is not generic; it cannot be parameterized with arguments <B>
Run Code Online (Sandbox Code Playgroud)

BTW:是否可以使create()方法静态?

Joa*_*uer 40

由于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;
    }
}
Run Code Online (Sandbox Code Playgroud)

一个小缺点是,如果要实例化以下内容,则必须将类型名称写入三次(1)FruitHandlerFactory:

FruitHandlerFactory fhf = new FruitHandlerFactory<OrangeHandler,Orange>(OrangeHandler.class, Orange.class);
Run Code Online (Sandbox Code Playgroud)

你可以通过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);
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

FruitHandlerFactory fhf = FruitHandlerFactory.createFactory(OrangeHandler.class, Orange.class);
Run Code Online (Sandbox Code Playgroud)