Java获取泛型T的类型 T.class

旧城等待, 2022-05-18 05:12 362阅读 0赞
  1. import java.lang.reflect.ParameterizedType;
  2. import java.lang.reflect.Type;
  3. public class Main{
  4. public static void main(String[] args)
  5. {
  6. Foo<String> foo = new Foo<String>(){};
  7. // 在类的外部这样获取
  8. Type type = ((ParameterizedType)foo.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
  9. System.out.println(type);
  10. // 在类的内部这样获取
  11. System.out.println(foo.getTClass());
  12. }
  13. }
  14. abstract class Foo<T>{
  15. public Class<T> getTClass()
  16. {
  17. Class<T> tClass = (Class<T>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
  18. return tClass;
  19. }
  20. }

输出:

  1. class java.lang.String
  2. class java.lang.String

上面的代码不是万能的,只有实例化T的子类才能按上述方法获得T的实际类型,
如果子类没有实例化T,则无法获取T的实际类型;
比如,class Child 并没有实例化T,所以得不到String.class;

  1. import java.lang.reflect.ParameterizedType;
  2. import java.lang.reflect.Type;
  3. public class Main{
  4. public static void main(String[] args){
  5. //区别在new Child<String>()没有{}匿名类
  6. Foo<String> foo = new Child<String>();
  7. // 在类的外部这样获取
  8. Type type = ((ParameterizedType)foo.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
  9. System.out.println(type);
  10. // 在类的内部这样获取
  11. System.out.println(foo.getTClass());
  12. }
  13. }
  14. abstract class Foo<T>{
  15. public Class<T> getTClass()
  16. {
  17. Class<T> tClass = (Class<T>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
  18. return tClass;
  19. }
  20. }
  21. class Child<T> extends Foo<T>{
  22. }

输出:

  1. Exception in thread "main" java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
  2. at com.hankcs.Main.main(Main.java:9)
  3. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  4. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
  5. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  6. at java.lang.reflect.Method.invoke(Method.java:606)

有一种解决方式,父类本身不获取泛型的具体类型,仅提供抽象方法,由子类来提供具体的类型

  1. public abstract class Foo<T> {
  2. public abstract Class getEntityClass();
  3. }
  4. public class Child extends Foo<String> {
  5. public Class getEntityClass() {
  6. return String.class;
  7. }
  8. }

对于获取泛型的方法,比较完整的代码如下:

  1. import java.lang.reflect.ParameterizedType;
  2. import java.lang.reflect.Type;
  3. public class GenericsUtils {
  4. /**
  5. * 通过反射,获得定义Class时声明的父类的范型参数的类型. 如public BookManager extends
  6. * GenricManager<Book>
  7. *
  8. * @param clazz The class to introspect
  9. * @return the first generic declaration, or <code>Object.class</code> if cannot be determined
  10. */
  11. public static Class getSuperClassGenricType(Class clazz) {
  12. return getSuperClassGenricType(clazz, 0);
  13. }
  14. /**
  15. * 通过反射,获得定义Class时声明的父类的范型参数的类型. 如public BookManager extends GenricManager<Book>
  16. *
  17. * @param clazz clazz The class to introspect
  18. * @param index the Index of the generic ddeclaration,start from 0.
  19. */
  20. public static Class getSuperClassGenricType(Class clazz, int index)
  21. throws IndexOutOfBoundsException {
  22. Type genType = clazz.getGenericSuperclass();
  23. if (!(genType instanceof ParameterizedType)) {
  24. return Object.class;
  25. }
  26. Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
  27. if (index >= params.length || index < 0) {
  28. return Object.class;
  29. }
  30. if (!(params[index] instanceof Class)) {
  31. return Object.class;
  32. }
  33. return (Class) params[index];
  34. }
  35. }

转载来源:
http://blog.csdn.net/wangjunjun2008/article/details/43970217
http://www.hankcs.com/program/t-class.html
https://www.cnblogs.com/sirab415/p/6133533.html

转载于:https://blog.csdn.net/changsa65/article/details/78790881

发表评论

表情:
评论列表 (有 0 条评论,362人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Java获取类型信息

    根据使用泛型位置的不同可以分为:声明侧泛型、使用侧泛型。 声明侧的泛型信息被记录在Class文件的Constant pool中以Signature的形式保存。而使用侧的泛型信

    相关 Java 如何获取TT.class当参数

    先说需求,本意是想在父类里面实现一些最基础的方法,然后子类只需要简单的继承,然后就可以有大部分方法可以使用了。我这儿实际就是一个crud的接口,然后给这个接口来个base实现,