JAVA反射_TYPE类型(转载)

原文出处:https://blog.csdn.net/kingdam578/article/details/78656626

java.lang.reflect
接口 Type

所有已知子接口:
    GenericArrayType, ParameterizedType, TypeVariable<D>, WildcardType

所有已知实现类:
    Class 

public interface Type

Type 是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。

从以下版本开始:

    1.5 

重点是上面的“所有类型”,它并不是我们平常工作中经常使用的 int、String、List、Map等数据类型,而是从Java语言角度来说,对基本类型、引用类型向上的抽象。

Type体系中类型的包括:原始类型(Class)、参数化类型(ParameterizedTypes)、数组类型(GenericArrayType)、类型变量(TypeVariable)、基本类型;

原始类型,不仅仅包含我们平常所指的类,还包括枚举、数组、注解等;

参数化类型,就是我们平常所用到的泛型List、Map;

数组类型,并不是我们工作中所使用的数组String[] 、byte[],而是带有泛型的数组,即T[] ;

基本类型,也就是我们所说的java的基本类型,即int,float,double等。

1.ParameterizedType
ParameterizedType 表示参数化类型,也就是泛型,如 Collection<String>。
需要注意的是,并不只是 Collection<String> 才是 parameterized,任何类似于 ClassName 这样的类型都是 ParameterizedType,
比如下面的这些都是 parameterizedType:

  1.  Map<String, Person> map;
  2.  Set<String> set1;
  3.  Class<?> clz;
  4.  Holder<String> holder;
  5.  List<String> list;
  6.   
  7.  //自定义的泛型类
  8.  public class Demo<T> {
  9.   
  10.  }
  11.  //自定义接口
  12.  public interface Call<T> {
  13.  
  14.  }

获取ParameterizedType的例子:

  1.  public class ParameterizedTest<T> {
  2.  
  3.  private List<T> list = null;
  4.   
  5.  public static void main(String[] args) {
  6.  
  7.  try {
  8.  Field field = ParameterizedTest.class.getDeclaredField("list");
  9.  
  10.  Type type = field.getGenericType();//method的返回类型如果是泛型,可以用method.getGenericReturnType()获取
  11.   
  12.  if (type instanceof ParameterizedType) {
  13.  System.out.println(type);
  14.  }
  15.   
  16.  } catch (NoSuchFieldException e) {
  17.  e.printStackTrace(); 
  18. }
  19.   
  20.  
  21.  }
  22.  }
  1.  public class Student {
  2.  private int id;
  3.  
  4.  public Student(int id) {
  5.  this.id = id;
  6.  }
  7.  }
  8.   
  9.  public class ParameterizedTest<T> {
  10.   
  11.  public ParameterizedTest() {
  12.  Class clazz=this.getClass();
  13.  //getSuperclass()获得该类的父类
  14.  System.out.println(clazz.getSuperclass());
  15.  //getGenericSuperclass()获得带有泛型的父类
  16.  //Type是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。
  17.  Type type=clazz.getGenericSuperclass();
  18.  System.out.println(type);
  19.  //ParameterizedType参数化类型,即泛型
  20.  ParameterizedType p=(ParameterizedType)type;
  21.  //getActualTypeArguments获取参数化类型的数组,泛型可能有多个
  22.  Class c=(Class) p.getActualTypeArguments()[0];
  23.  System.out.println(c);
  24.  }
  25.  }
  26.   
  27.  public class SubParameterizedTest extends ParameterizedTest<Student> {
  28.   
  29.  public static void main(String args[]) {
  30.   
  31.  SubParameterizedTest st = new SubParameterizedTest();
  32.   
  33.  }
  34.  }
  1.  输出:
  2.  class bean.ParameterizedTest
  3.  bean.ParameterizedTest<bean.Student>
  4.  class bean.Student
  5.   

ParameterizedType 的几个主要方法:

  1.  Type[] getActualTypeArguments(); //返回表示此类型实际类型参数的 Type 对象的数组。
  2.  Type getRawType();//返回 Type 对象,表示声明此类型的类或接口。
  3.  Type getOwnerType();//返回 Type 对象,表示此类型是其成员之一的类型。

1.1 getActualTypeArguments

 获取泛型中的实际类型,可能会存在多个泛型,例如Map<K,V>,所以会返回Type[]数组:

  1.  public class ParameterizedTest<T> {
  2.   
  3.  private Map<String, Integer> list = null;
  4.   
  5.  public static void main(String[] args) {
  6.  
  7.  try {
  8.  Field field = ParameterizedTest.class.getDeclaredField("list");
  9.   
  10.  Type type = field.getGenericType();
  11.  
  12.  if (type instanceof ParameterizedType) {
  13.  ParameterizedType pType = (ParameterizedType) type;
  14.  Type[] types = pType.getActualTypeArguments();
  15.   
  16.  System.out.println(types[0]);// class java.lang.String
  17.  System.out.println(types[1]);// class java.lang.Integer
  18.  }
  19.   
  20.  } catch (NoSuchFieldException e) {
  21.  e.printStackTrace();
  22.  }
  23.   
  24.   
  25.  }
  26.  }

值得注意的是,无论<>中有几层嵌套(List<Map<String,Integer>),getActualTypeArguments()方法永远都是脱去最外层的<>(也就是List<>),

将<>号内的内容(Map<String,Integer>)返回;

我们经常遇到的List<T>,通过getActualTypeArguments()方法,得到的返回值是TypeVariableImpl对象,也就是TypeVariable类型(后面介绍)

1.2 getRawType

获取声明泛型的类或者接口,也就是泛型中<>前面的那个值:

  1.  public class ParameterizedTest<T> {
  2.  
  3.  private Map<String, Integer> list = null;
  4.  
  5.  public static void main(String[] args) {
  6.  
  7.  try {
  8.  Field field = ParameterizedTest.class.getDeclaredField("list");
  9.   
  10.  Type type = field.getGenericType();
  11.   
  12.  if (type instanceof ParameterizedType) {
  13.  ParameterizedType pType = (ParameterizedType) type;
  14.   
  15.  Type t = pType.getRawType();//interface java.util.Map
  16.   
  17.  System.out.println(t);
  18.  }
  19.  
  20.  } catch (NoSuchFieldException e) {
  21.  e.printStackTrace();
  22.  }
  23.  }
  24.  }

1.3 getOwnerType
(这个比较少用到) 返回的是这个 ParameterizedType 所在的类的 Type (注意当前的 ParameterizedType 必须属于所在类的 member)。
比如 Map<String,Person> map 这个 ParameterizedType 的 getOwnerType() 为 null,而 Map.Entry<String, String>entry 的 getOwnerType() 为 Map 所属于的 Type。

 

2.TypeVariable

类型变量,即泛型中的变量;例如:T、K、V等变量,可以表示任何类,实际的Java类型是TypeVariableImpl(TypeVariable的子类)。在这需要强调的是,
TypeVariable代表着泛型中的变量,而ParameterizedType则代表整个泛型。此外,还可以对类型变量加上extend限定,这样会有类型变量对应的上限。

  1.  public class ParameterizedTest<T> {
  2.   
  3.  private List<T> list = null;
  4.   
  5.  public static void main(String[] args) {
  6.  
  7.  try {
  8.  Field field = ParameterizedTest.class.getDeclaredField("list");
  9.   
  10.  Type type = field.getGenericType();//获取List<T>
  11.   
  12.  if (type instanceof ParameterizedType) {
  13.  ParameterizedType pType = (ParameterizedType) type;
  14.  
  15.  Type[] t = pType.getActualTypeArguments();// 获取T
  16.  
  17.  System.out.println(t[0].getClass().getName());//T的类型 sun.reflect.generics.reflectiveObjects.TypeVariableImpl
  18.  }
  19.   
  20.  } catch (NoSuchFieldException e) {
  21.  e.printStackTrace();
  22.  }
  23.  }
  24.  }

在TypeVariable接口中,有3个方法,分别为getBounds()、getGenericDeclaration()、getName():

 2.1 getBounds

获得该类型变量的上限,也就是泛型中extend右边的值;例如 List<T extends Number> ,Number就是类型变量T的上限;
如果我们只是简单的声明了List<T>(无显式定义extends),那么默认为Object。

  1.  //无显式定义extends:
  2.  public class ParameterizedTest<T> {
  3.   
  4.  private T list = null;
  5.  
  6.  public static void main(String[] args) {
  7.  
  8.  try {
  9.  Field field = ParameterizedTest.class.getDeclaredField("list");
  10.  
  11.  Type type = field.getGenericType();
  12.  if (type instanceof TypeVariable) {
  13.  TypeVariable tv = (TypeVariable) type;
  14.  Type[] types = tv.getBounds();
  15.  for (Type t : types) {
  16.  System.out.println(t);//class java.lang.Object
  17.  }
  18.  }
  19.  } catch (NoSuchFieldException e) {
  20.  e.printStackTrace();
  21.  }
  22.  }
  23.  }
  1.  //显式定义extends:
  2.  public class ParameterizedTest<T extends Number & Serializable & Comparable> {
  3.   
  4.  private T t;
  5.   
  6.  public static void main(String[] args) {
  7.   
  8.  try {
  9.  Field field = ParameterizedTest.class.getDeclaredField("t");
  10.   
  11.  Type type = field.getGenericType();
  12.   
  13.  if (type instanceof TypeVariable) {
  14.  TypeVariable tType = (TypeVariable) type;
  15.  
  16.  Type[] types = tType.getBounds();
  17.  
  18.  for (Type t : types) {
  19.  System.out.println(t);//class java.lang.Number interface java.io.Serializable interface java.lang.Comparable
  20.  }
  21.  }
  22.   
  23.  } catch (NoSuchFieldException e) {
  24.  e.printStackTrace();
  25.  }
  26.  }
  27.  }

2.2 getGenericDeclaration

获取声明该类型变量实体(是Class, Constructor, Method)

  1.  public class ParameterizedTest<T> {
  2.   
  3.  private T t;
  4.  
  5.  public static void main(String[] args) {
  6.  
  7.  try {
  8.  Field field = ParameterizedTest.class.getDeclaredField("t");
  9.  
  10.  Type type = field.getGenericType();
  11.  
  12.  if (type instanceof TypeVariable) {
  13.  TypeVariable tType = (TypeVariable) type;
  14.  
  15.  GenericDeclaration genericDeclaration = tType.getGenericDeclaration();
  16.  System.out.println(genericDeclaration);//class com.king.testreflect.ParameterizedTest
  17.  }
  18.  
  19.  } catch (NoSuchFieldException e) {
  20.  e.printStackTrace();
  21.  }
  22.  }
  23.  }

2.3 getName
获取类型变量在源码中定义的名称。

  1.  public class ParameterizedTest<T> {
  2.   
  3.  private T t;
  4.   
  5.  public static void main(String[] args) {
  6.   
  7.  try {
  8.  Field field = ParameterizedTest.class.getDeclaredField("t");
  9.   
  10.  Type type = field.getGenericType();
  11.   
  12.  if (type instanceof TypeVariable) {
  13.  TypeVariable tType = (TypeVariable) type;
  14.  
  15.  String name = tType.getName();
  16.  System.out.println(name);//T
  17.  }
  18.   
  19.  } catch (NoSuchFieldException e) {
  20.  e.printStackTrace();
  21.  }
  22.  }
  23.  }

说到TypeVariable类,就不得不提及Java-Type体系中另一个比较重要的接口---GenericDeclaration;
含义为:声明类型变量的所有实体的公共接口;也就是说该接口定义了哪些地方可以定义类型变量(泛型);
通过查看源码发现,GenericDeclaration下有三个子类,分别为Class、Method、Constructor;也就是说,我们定义泛型只能在一个类中这3个地方自定义泛型;
 java.lang.reflect
接口 GenericDeclaration

所有已知实现类:
    Class, Constructor, Method 
此时,我们不禁要问,我们不是经常在类中的属性声明泛型吗,怎么Field没有实现 GenericDeclaration接口呢?
其实,我们在Field中并没有声明泛型,而是在使用泛型而已!不信,我们实际上代码来看看!

1.在Class上定义泛型:

  1.  public class GenericDeclarationTest<T> {
  2.  //Class定义泛型
  3.  }

2.直接在构造方法上定义泛型

  1.  public class GenericDeclarationTest<T> {
  2.  public <T> GenericDeclarationTest(T t) {
  3.  //泛型构造函数
  4.  }
  5.  }

3.直接在普通方法上定义泛型 

  1. public class GenericDeclarationTest<T> {
  2.  public <T> test(T t) {
  3.  //泛型方法
  4.  }
  5.  }

4.直接在属性上定义(不支持)

  1.  public class GenericDeclarationTest {
  2.  private T t;
  3.  private List<T> list;
  4.  }

我们看到,如果不在Class上定义,属性上并不能直接使用!
所以,这也是我之前说的属性上并不是定义泛型,而是使用泛型,所以Field并没有实现GenericDeclaration接口!

3.GenericArrayType
泛型数组类型.
简单来说就是:范型数组,组成数组的元素中有范型,则实现了该接口; 它的组成元素是ParameterizedType或TypeVariable 类型

  1.  public class ParameterizedTest<T> {
  2.  
  3.  private T[] t;
  4.  private List<String>[] listArray;
  5.  
  6.  public static void main(String[] args) {
  7.  
  8.  try {
  9.  Field fieldT = ParameterizedTest.class.getDeclaredField("t");
  10.   
  11.  Type typeT = fieldT.getGenericType();
  12.   
  13.  //sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl
  14.  System.out.println(typeT.getClass().getName());
  15.   
  16.  Field fieldListArray = ParameterizedTest.class.getDeclaredField("listArray");
  17.  Type typeListArray = fieldListArray.getGenericType();
  18.   
  19.  //sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl
  20.  System.out.println(typeListArray.getClass().getName());
  21.   
  22.  } catch (NoSuchFieldException e) {
  23.  e.printStackTrace();
  24.  }
  25.  }
  26.  }

在GenericArrayType接口中,仅有1个方法,就是getGenericComponentType();


3.1 getGenericComponentType
返回泛型数组中元素的Type类型,即List<String>[] 中的 List<String>(ParameterizedTypeImpl)、T[] 中的T(TypeVariableImpl);
值得注意的是,无论是几维数组,getGenericComponentType()方法都只会脱去最右边的[],返回剩下的值。

4.WildcardType
?---通配符表达式,表示通配符泛型,例如:List<? extends Number> 和 List<? super Integer>。
但是WildcardType并不属于Java-Type中的一种。
extends 用来指定上边界,没有指定的话上边界默认是 Object, super 用来指定下边界,没有指定的话为 null。

    1.  public class ParameterizedTest<T> {
    2.  
    3.  private List<? extends Number> listNum; 
    4. private List<? super String> listStr;
    5.  
    6.  public static void main(String[] args) {
    7.  
    8.  try {
    9.  Field fieldNum = ParameterizedTest.class.getDeclaredField("listNum");
    10.   
    11.  Type typeNum = fieldNum.getGenericType();
    12.   
    13.  if (typeNum instanceof ParameterizedType) {
    14.  ParameterizedType parameterizedType = (ParameterizedType) typeNum;
    15.  Type[] types = parameterizedType.getActualTypeArguments();
    16.  if (types[0] instanceof WildcardType) {
    17.  WildcardType wType = (WildcardType) types[0];
    18.  Type[] upperTypes = wType.getUpperBounds();
    19.  for (Type t : upperTypes) {
    20.  System.out.println(t);//class java.lang.Number
    21.  }
    22.  Type[] lowerTypes = wType.getLowerBounds();//null
    23.  for (Type t : lowerTypes) {
    24.  System.out.println(t);
    25.  }
    26.  }
    27.   
    28.  }
    29.   
    30.  Field fieldList = ParameterizedTest.class.getDeclaredField("listStr");
    31.  
    32.  Type typeList = fieldList.getGenericType();
    33.   
    34.  if (typeList instanceof ParameterizedType) {
    35.  ParameterizedType parameterizedType = (ParameterizedType) typeList;
    36.  Type[] types = parameterizedType.getActualTypeArguments();
    37.  if (types[0] instanceof WildcardType) {
    38.  WildcardType wType = (WildcardType) types[0];
    39.  Type[] upperTypes = wType.getUpperBounds();
    40.  for (Type t : upperTypes) {
    41.  System.out.println(t);// class java.lang.Object
    42.  }
    43.   
    44.  Type[] lowerTypes = wType.getLowerBounds();
    45.  for (Type t : lowerTypes) {
    46.  System.out.println(t);//class java.lang.String
    47.  }
    48.  }
    49.   
    50.  }
    51.   
    52.  
    53.  } catch (NoSuchFieldException e) {
    54.  e.printStackTrace();
    55.  }
    56.  }
    57.  }
posted @ 2018-07-15 19:06  青青子衿J  阅读(130)  评论(0)    收藏  举报