views:

168

answers:

7

How can i achieve this?

public class GenericClass<T>
{
    public Type getMyType()
    {
        //How do I return the type of T?
    }
}

Everything I have tried so far always returns type Object rather than the specific type used.

Thanks a lot.

+5  A: 

I dont think you can, Java uses type erasure when compiling so your code is compatible with applications and libraries that were created pre-generics.

http://download-llnw.oracle.com/javase/tutorial/java/generics/erasure.html

Dimitar
Jup, it's impossible. Java would need reified generics for that to work.
Henning
+1  A: 

You can't. If you add a member variable of type T to the class (you don't even have to initialise it), you could use that to recover the type.

andrewmu
Oops, ok. You *do* have to initialise it from a constructor.
andrewmu
+5  A: 

Generics are not reified at run-time. This means the information is not present at run-time.

Adding generics to Java while mantaining backward compatibility was a tour-de-force (you can see the seminal paper about it: Making the future safe for the past: adding genericity to the Java programming language).

There is a rich literature on the subject, and some people are dissatisfied with the current state, some says that actually it's a lure and there is no real need for it. You can read both links, I found them quite interesting.

ewernli
+1: Some very interesting links there that cover the background pretty well.
Donal Fellows
+1  A: 

I have seen something like this

private Class<T> persistentClass;

public Constructor() {
    this.persistentClass = (Class<T>) ((ParameterizedType) getClass()
                            .getGenericSuperclass()).getActualTypeArguments()[0];
 }

in the hibernate GenericDataAccessObjects Example

K. Claszen
+5  A: 

As others mentioned, it's impossible only doable with reflection.

If you really need the type, this is the usual (type-safe) workaround pattern:

public class GenericClass<T> {

     private final Class<T> type;

     public GenericClass(Class<T> type) {
          this.type = type;
     }

     public Class<T> getMyType() {
         return this.type;
     }
}
Henning
+3  A: 

Java generics are mostly compile time, this means that the type information is lost at runtime.

class GenericCls<T>
{
    T t;
}

will be compiled to something like

class GenericCls
{
   Object o;
}

To get the type information at runtime you have to add it as an argument of the ctor.

class GenericCls<T>
{
     private Class<T> type;
     public GenericCls(Class<T> cls)
     {
        type= cls;
     }
     Class<T> getType(){return type;}
}

Example:

GenericCls<?> instance = new GenericCls<String>(String.class);
assert instance.getType() == String.class;
josefx
+1  A: 

Sure, you can.

Java does not use the information at compile time, for backwards compatibility reasons. But the information is actually present as metadata and can be accessed via reflection (but it is still not used for type-checking).

From the official API:

http://download.oracle.com/javase/6/docs/api/java/lang/reflect/ParameterizedType.html#getActualTypeArguments%28%29

However, for your scenario I would not use reflection. I'm personally more inclined to use that for framework code. In your case I would just add the type as a constructor param.

Joeri Hendrickx
Ah, wow! That's very interresting.
Henning
Seems related: http://www.artima.com/weblogs/viewpost.jsp?thread=208860
ewernli