Search code examples
javagenericsreflectionfactory-pattern

How can I use reflection to build generic subtypes?


I'm using the Factory pattern to hide some instance creation complexity. I have this:

class FooInt extends Foo<int>;

I want to do:

class<Foo<?>> fooType = FooInt.class;

All derived types of Foo have a single constructor taking 2 arguments. So I need to use reflection to create instances of subtypes:

Constructor<Foo<?>> ctor = fooType.getContructor(Blah.class, Blahblah.class);
return ctor.newInstance(blah, blahblah);

But javac says:

"Type mismatch: cannot convert from Class<FooInt> to Class<Foo<?>>"

What am I doing wrong? Is it possible to use reflection this way?


Solution

  • try: Class<? extends Foo<?>> fooType = FooInt.class;

    One other point is:

    • the Class Type is Class not class (upper case C);
    • you can not use primities in generics (use Integer instead of int)

    Added: and this is how it works:

    public class Foo<T> {
    
        private T value;
    
        public Foo(T value) {    
            this.value = value;
        }      
    }
    
    public class FooInt extends Foo<Integer>{
        public FooInt(Integer value) {
            super(value);
        }
    }
    
    public class FooDouble extends Foo<Double>{
        public FooDouble(Double value) {
            super(value);
        }
    }
    

    The factory (at least only one line, but a lot of exceptions ;-) ):

    import java.lang.reflect.InvocationTargetException;
    
    public class Factory {
    
        <P, T extends Foo<P>> T build(Class<T> clazz, P param)
                throws IllegalArgumentException, SecurityException,
                   InstantiationException, IllegalAccessException,
                   InvocationTargetException, NoSuchMethodException {
            return clazz.getConstructor(param.getClass()).newInstance(param);
        }
    
        public static void main(String[] args)
                throws IllegalArgumentException, SecurityException,
                    InstantiationException, IllegalAccessException,
                    InvocationTargetException, NoSuchMethodException {
    
            Factory f = new Factory();
    
            System.out.println(f.build(FooInt.class, Integer.valueOf(1)));
            System.out.println(f.build(FooDouble.class, Double.valueOf(1.1)));
        }
    }