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

39
假设有两个接口:
public interface FruitHandler<T extends Fruit>
{
    setFruit(T fruit);
    T getFruit();
}

public interface Fruit
{
}

现在我想要一个工厂来创建水果处理器(例如AppleHandlerOrangeHandler,...),但是FruitHandlerFactory不知道如何实现接口的类的必要信息(就像java parameterized generic static factory中一样)。FruitHandlerFactory应该这样工作(其中OrangeHandler实现FruitHandlerOrange实现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()方法定义为静态的?


5
好问题,很棒的代码片段来说明。 - sje397
2个回答

41

由于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);
你可以通过在你的 FruitHandlerFactory 上创建一个 staticcreateFactory() 方法来稍微减少这种情况:
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);

在这个方法中,您需要一个公共的零参数构造函数。当对象只能有私有构造函数时,有什么解决方案吗? - Ofek Regev

2

来自这个问题

也许可以尝试这个?

public class FruitHandlerFactory<A extends FruitHandler<B>, B extends Fruit>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接