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

时间:2011-05-23 05:59:05

标签: java generics

我们假设有两个接口:

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

public interface Fruit
{
}

现在我想要一个工厂来创建FruitHandlers(例如AppleHanderOrangeHandler,...),但是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>

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

2 个答案:

答案 0 :(得分: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;
    }
}

一个小缺点是,如果要实例化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);

答案 1 :(得分:2)

来自this question

或许试试这个?

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