2011-05-23 48 views
31

假设两个接口:通用工厂未知的实现类

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

public interface Fruit 
{ 
} 

现在我想一个工厂来创建FruitHandlers(如AppleHanderOrangeHandler,...),但FruitHandlerFactory不知道neccessary关于实施两个接口的类(如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()方法是静态的?

+2

优秀的问题和伟大的代码片段来说明。 – sje397 2011-05-23 06:02:10

回答

39

由于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; 
    } 
} 

A小调的缺点是,你必须写类型名三次(1)如果你想实例化一个FruitHandlerFactory

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); 
+0

这真是太棒了...... :-)谢谢你这个优秀而全面的答案! – Thor 2011-05-23 06:55:05

2

this question

也许尝试呢?

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