2011-05-23 80 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>