8

When it comes to classes without generics, i can access this .class attribute like this:

class Foo{
    Class<Foo> getMyClass(){
        return Foo.class;
    }
}

but how do i access this ".class" attribute if Foo has a generic? like this:

class Foo<T>{
    Class<Foo<T>> getMyClass(){
        return (Foo<T>).class //this doesnt work...
    }
}

i have tried to return Foo.class, but this is not going to work: "cannot cast from Class<Foo> to Class<Foo<T>>".

How can i access Foo<T>'s class?

Reimeus
  • 158,255
  • 15
  • 216
  • 276
pr00thmatic
  • 815
  • 9
  • 14
  • possible duplicate of [Why should I care that Java doesn't have reified generics?](http://stackoverflow.com/questions/1927789/why-should-i-care-that-java-doesnt-have-reified-generics) – McDowell Jul 13 '13 at 22:13
  • no, it is not a duplicate. The answers on that question are indicating how to create an instance from a generic type; my question is about accessing to the class of a template class. I would want to make an instance of `Foo` via `Class> x; x.newInstance()` – pr00thmatic Jul 13 '13 at 22:22
  • possible duplicate of [Can I call .class on a generic type in Java?](http://stackoverflow.com/questions/10257416/can-i-call-class-on-a-generic-type-in-java), [Java Generics Pass .class Reference](http://stackoverflow.com/questions/12050626/java-generics-pass-class-reference), and [How to get parametrized Class instance](http://stackoverflow.com/questions/71585/how-to-get-parametrized-class-instance). – Paul Bellora Jul 13 '13 at 22:32
  • `Class>` is meaningless due to type erasure and what the `Class` class does. Java is not C++. Generics are not templates. In your example above, `x.newInstance()` will return `Foo>` by definition since generics are a compile-time idea that does not exist at runtime, which is when reflection occurs. –  Jul 13 '13 at 23:04
  • 1
    FYI if you really want to use generics with reflection, you need to perform type casts. The compiler will likely mark them as unsafe, so you may need a `@SuppressWarnings()` annotation. I would double and triple check to make sure those casts really are safe. Warnings are there to help detect logic errors, but with reflection and generics, there really is no safe way out of it. Just be careful that you are not writing any "undocumented features." –  Jul 13 '13 at 23:06

2 Answers2

8

You can always do this:

class Foo<T>{
    Class<Foo<T>> getMyClass(){
        return (Class<Foo<T>>)(Class<?>)Foo.class
    }
}

You will have unchecked cast warnings, because it indeed is unsafe -- as others have mentioned, the returned class object is not any more "Foo<T>'s class" as "Foo<SomethingElse>'s class".

newacct
  • 119,665
  • 29
  • 163
  • 224
  • This works, but you still get a warning... Is there a way of doing it without getting a warning? – Martin Oct 29 '15 at 13:49
  • @Martin: No, because there is not really any such thing as a `Class>`. There is only one `Class` object for `Foo`. – newacct Oct 29 '15 at 17:25
3

There isn't a way, because of type erasure. This:

Foo<T>.class

... can not be obtained at runtime, it will always be the same type no matter what's the type of T. At runtime only this exists:

Foo.class
Óscar López
  • 232,561
  • 37
  • 312
  • 386