Let\'s assume two interfaces:
public interface FruitHandler
{
setFruit(T fruit);
T getFruit();
}
public interface Fruit
{
}
<
Since generics in Java are implemented using erasure, the type information of FruitHandlerFactory
will not be available at runtime, which means you can't instantiate A
(or B
) this way.
You can, however pass in a Class
object of the correct type to work around this:
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 minor drawback is that you'll have to write the type names three times(1) if you want to instantiate a FruitHandlerFactory
:
FruitHandlerFactory fhf = new FruitHandlerFactory<OrangeHandler,Orange>(OrangeHandler.class, Orange.class);
You can somewhat reduce that by producing a static
createFactory()
method on your 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);
}
and use it like this:
FruitHandlerFactory fhf = FruitHandlerFactory.createFactory(OrangeHandler.class, Orange.class);
From this question:
Perhaps try this?
public class FruitHandlerFactory<A extends FruitHandler<B>, B extends Fruit>