5

I have a generic class, says :

MyClass<T>

Inside a method of this class, I would like to test the type of T, for example :

void MyMethod()
{

    if (T == String)
        ...
    if (T == int)
        ...
}

how can I do that ?

Thanks for your help

Tim
  • 2,887
  • 10
  • 33
  • 33

7 Answers7

12

You can't, normally, due to type erasure. See Angelika Langer's Java Generics FAQ for more details.

What you can do is pass a Class<T> into your constructor, and then check that:

public MyClass<T>
{
    private final Class<T> clazz;

    public MyClass(Class<T> clazz)
    {
        this.clazz = clazz;
    }

    public void myMethod()
    {
        if (clazz == String.class)
        {
           ...
        }
    }
}

Note that Java does not allow primitives to be used for type arguments though, so int is out...

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 4
    Ew. Java is gross for this kind of thing. – Conrad Meyer Dec 11 '09 at 08:50
  • 4
    which honestly you shouldn't need if you design your classes properly. – Bozho Dec 11 '09 at 09:02
  • I understand, maybe my desing is bad. I have a view that can be applyed to 2 models, except for some little things depending on the type of the object model. I don't want to create 2 views that are quite the same, but they are not working exactly the same. – Tim Dec 11 '09 at 09:19
  • 1
    With all respect for "proper design", I dislike it when a language tells me what "proper design" is. Notwithstanding that this might be bad design, I find "Java does not need to do this because you designed it improperly" is possibly not the best reply. – Cornelius May 19 '11 at 12:02
8

Because of type erasure you can't... mostly. But there is one exception to that. Consider:

class A {
  List<String> list;
}

public class Main {
  public static void main(String args[]) {
    for (Field field : A.class.getDeclaredFields()) {
      System.out.printf("%s: %s%n", field.getName(), field.getGenericType());
    }
  }
}

Output:

list: java.util.List<java.lang.String>

If you need the class object, this is how you generally handle it:

public <T> T createObject(Class<T> clazz) {  
  return clazz.newInstance();
}

ie by passing the class object around and deriving the generic type from that class.

cletus
  • 616,129
  • 168
  • 910
  • 942
3

Additionally to cletus one exception I've mine: super type tokens. The super type token will preserve the type information.

new Type<Set<Integer>>() {}

The type information can be retrieved with Class.getGenericSuperClass.

Thomas Jung
  • 32,428
  • 9
  • 84
  • 114
1
if (object instanceof String)
   System.out.println("object is a string");
oliver31
  • 2,523
  • 3
  • 19
  • 25
0

As it was already stated you can get only generics-related information available at the static byte code level.

It's possible to resolve type arguments values and check if one type may be used in place of another then.

denis.zhdanov
  • 3,734
  • 20
  • 25
0

if you have subclass B extends A that should match, too, the approach clazz == A.class. Doesn't work. You should then use A.class.isInstance(b) where b is an object of type B.

bertolami
  • 2,896
  • 2
  • 24
  • 41
0

If you want to do different things for different types would it still be generic?

fastcodejava
  • 39,895
  • 28
  • 133
  • 186