9

I have the following Java class

public class MyClass <T extends MyInterface> implements RowMapper<MyInterface>

I'm implementing the following method:

@Override
public T mapRow(ResultSet rs, int arg1) throws SQLException {

How can I create an instance of 'T' type on that class?

I tried to define the T type class and use "myInstance.newInstance()" but I was unable to define it. Sending the Class as a parameter to the method and using the "newInstance()" method works, but I want to be able to do so without having to pass it as a param. Thanks!

Omri
  • 1,058
  • 3
  • 14
  • 26

4 Answers4

26

Java generics are implemented by erasure which means there will be no parameter type information at runtime. You won't know the T class at runtime (there is not such T.class). So you need to pass the Class object as a method parameter in order to do what you want.

dcernahoschi
  • 14,968
  • 5
  • 37
  • 59
  • 1
    Heck, this has been asked a million times in SO, but this is the only answer that actually goes to the point (albeit could start with a straight **you can't**). Thanks a lot! – Bruno Brant Dec 30 '15 at 18:51
  • @Bruno - million times is about right, and one would think that the Java designers would take the hint and add that to the java's reflection already... – Deian Jun 12 '17 at 14:21
10

You are loosing all information about type when passing object into generic class/function.

The only way you can do this - pass Class object to constructor\function:

static class Gen <T>{

    private Class<T> mClass;

    public Gen(Class<T> cls){
        mClass = cls;
    }

    public T get(){
        try{
            return mClass.newInstance();
        }catch(Exception e){
            e.printStackTrace();
            return null;
        }
    }
}

static class A{
    public String name = "A!";
}

public static void main(String[] args) {
    Gen<A> g = new Gen<A>(A.class);
    A a = g.get();
    System.out.println(a.name);
}
Dmitry Zaytsev
  • 23,650
  • 14
  • 92
  • 146
1

Unfortunately, due to type erasure, you can't do what you want.

You will have to explicitly tell your class which type it needs to instantiate, either by telling it the Class or, perhaps more elegantly, giving it a Factory to create instances.

ᴇʟᴇvᴀтᴇ
  • 12,285
  • 4
  • 43
  • 66
1

It's possible to extract the class to which T was bound in a particular sub-class, though that's not very easy:

http://www.artima.com/weblogs/viewpostP.jsp?thread=208860

I've a slightly better version of the code in that post here:

http://github.com/ISA-tools/jUtils/blob/master/src/main/java/uk/ac/ebi/utils/reflection/ReflectionUtils.java

http://github.com/ISA-tools/jUtils/blob/master/src/test/java/uk/ac/ebi/utils/reflection/ReflectionUtilsTest.java

This approach isn't much fast either, so if performance is a concern, an rougher alternative could be to pass T and an instance of Class<T> too where you need.

Of course after having got such class, you need to use reflection to instantiate it.

zakmck
  • 2,715
  • 1
  • 37
  • 53