简体   繁体   中英

Get the the type of the class of a generic type?

A class which has a method declared as this:

public class A{
    public <T> T test(java.lang.Class<T> classOfT)
}

Normally it can be called against an object like this:

A a = new A()
String s = "test";
a.test(String.class); //I wrote this as s.class at first,which is wrong.Thanks Nick.

Now I would like to generalize the object passed to it, so I declare a class like this:

public class B <T>{
    private A a   = new A();
    private T obj = null;
    T test(){return a.test(obj.getClass()); } 
}

But the code wont' compile.I am wondering is it possible to achieve my goal?

Thank you in advance Java gurus;)

T obj = ...;
obj.getClass()

The last line returns Class<? extends T> Class<? extends T> -- but T is unbounded, so it is basically bounded by Object , which means it returns Class<? extends Object> Class<? extends Object> , which is the same as Class<?> .

So doing this:

T test () { return a.test(obj.getClass()); }

Will actually invoke a.test with a parameter of type Class<?> , which returns an Object , and not a T .

Just cast the parameter to Class<T> or the return type to T and it should work -- although I am yet to understand why you need something like this. Also, there is this strange error in the original post:

 String s = "test";
 a.test(s.class);

Doing "test".class is wrong -- it should be String.class .

Class<T> clazz  = (Class<T>) obj.getClass();
return a.test(clazz);

Try

@SuppressWarnings("unchecked")
T test() {
    return (T) a.test(obj.getClass());
}

In complement of the other answers, when defining your function as

public class A{
    public <T> T test(java.lang.Class<T> classOfT) { ... }
}

if you are using the classOfT parameter just to determine the type of T , you might be better off defining your method with no parameter at all. For instance, do this instead of the above declaration:

public class A{
    public <T> T test() { ... }
}

That way you can just call it using this qualified method-call syntax. This is how I would rewrite your code:

public class A{
    public <T> T test() {
          // ...
    }        

    public static void main(String[] args) {
          A a = new A();
          String result = a.<String>test(); 
    }
}

public class B <T> {
    private A a = new A();

    T test() {
        return this.a.<T>test();
    }
}

This way you do not need to pass the generic A#test() function a class parameter, which would possibly have been unused at runtime. Of course if you do use the classOfT at runtime, this solution may not be that much interesting for you...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM