39

Isn't there any way to find the class-type of a generic?

if (T instanceof String) {
    // do something...
}

The above definitely does not compile.

someguy
  • 6,678
  • 12
  • 38
  • 55

4 Answers4

49

Generics are a compile time feature. Generics add checks at compile time which may not have any meaning at runtime. This is one example. You can only check the type of the object referenced which could be a super type in code. If you want to pass the type T you have do this explicitly.

void someMethod(Class<T> tClass) {
    if(String.class.isAssignableFrom(tClass)) 

or

void someMethod(Class<T> tClass, T tArg) {

Note: the type might not be the same,

someMethod(Number.class, 1);
Peter Lawrey
  • 498,481
  • 72
  • 700
  • 1,075
  • 2
    This is one of those answers that just nailed a bunch of things at once for me. – mtyson Jun 29 '16 at 16:19
  • what is this? e.g. I have `T var` and how to use it with this method? `someMethod(T)` won't work... What I don't understand? – user25 Aug 31 '16 at 09:49
  • @user25 I am not sure what you don't understand. Can you clarify what you mean? It sounds like a different question to me. – Peter Lawrey Aug 31 '16 at 10:00
  • @PeterLawrey http://stackoverflow.com/a/4704909/4548520 this works for me. This one I understood how to use: e.g I have `T var` and then I have to check type like this: `new Test().something(var)` – user25 Aug 31 '16 at 10:06
  • @user25 the only thing you can get here is the var.getClass () there is no way to get T if you do that. – Peter Lawrey Aug 31 '16 at 10:16
  • @PeterLawrey I got type of my `var`. It's all I wanted – user25 Aug 31 '16 at 10:55
  • @user25 ok, you can get the type of the object, but not the generic in this case. – Peter Lawrey Sep 01 '16 at 07:52
4

It won't compile because T is not a variable, but a place holder for a class that is defined at runtime. Here's a quick sample:

public class Test<T> {

public void something(T arg) {
    if (arg instanceof String) {
        System.out.println("Woot!");
    }
}

public static void main(String[] args) {
    Test<String> t = new Test<String>();
    t.something("Hello");
}

}
drekka
  • 18,723
  • 12
  • 67
  • 112
  • 1
    I don't think that will work in java. see Jon Skeet's answer http://stackoverflow.com/questions/313584/what-is-the-concept-of-erasure-in-generics-in-java – The Scrum Meister Jan 16 '11 at 10:54
  • @The Scrum Meister , it works for this specific case. I have tested it. – gigadot Jan 16 '11 at 11:03
  • 2
    This will work because you are using `instanceof` to test against a known type, not a generic. What doesn't work is saying `if (foo instanceof T)` where `foo` is some variable, because the type that `T` represents is not known at compile time. – William Feb 24 '15 at 18:17
4

if you have subclass

public class SomeClass extends SomeSubclass<String>{}

and

public class SomeSubclass<T> {}

then there is a way to discover type of T by executing code

Type t = getClass().getGenericSuperclass()
if (t instanceof ParameterizedType) {
    Type[] actualTypeArguments = ((ParameterizedType)t).getActualTypeArguments()
    // in simple cases actualTypeArguments will contain Classes, since Class implements Type
}

if your case are a bit more complex (? extends String)` take a look at org.ormunit.entity.AEntityAccessor#extractClass

Michael Anderson
  • 61,385
  • 7
  • 119
  • 164
Tomasz Krzyżak
  • 1,077
  • 8
  • 10
1

If you have specific field you can just check it like below:

private <T> String someMethod(T genericElement)
{
    if (String.class.isInstance(genericElement))
    {
        return (String) genericElement;
    }
...
Adir D
  • 480
  • 3
  • 13