泛型反射 -- T.class 的获取

1. 需求

在开发过程中,封装的过程中,避免不了要获得 泛型的class, 那么如何获取呢。

注意: 具体的解释在代码中
注意: 具体的解释在代码中
注意: 具体的解释在代码中

2. 名词的解释

在这之前呢,我们应该知道一些名词

  1. List<E> :E称为类型参数变量
  2. List<Integer> : Integer称为实际类型参数
  3. List<Integer> :List<Integer>称为参数化类型

3. 获取T.class

3.1 前提条件

再获取泛型的class之前呢,我想说的是:
获取T.class 的前提条件是

  1. 再父类中才能获取。
  2. 子类必须已经确定了父类的泛型,什么意思呢?比如这样
    public class Son extends Parent<String> {…}
    这样子就算是 子类再在继承的时候 已经确定了父类的泛型。
  3. 使用的时候,实例化子类

3.2 例子的类图

在这里插入图片描述

3.3 代码(具体的解释在代码中

3.3.1 Parent类代码

public class Parent<T> {
    
    

	private Class<T> clazz;
	
	/**
	 * 无参构造方法
	 */
	public Parent() {
    
    
		
		/**
		 * 获取直接父类
		 * 1. 注意,这个getClass() 方法获取的是谁的class呢?
		 * 	  如果是实例化的Parent的子类( new Son() ),那么实例化子类(Son)的时候,
		 *   必定会实例化Parent.所以此时getClass() 获取的是其子类(Son的)的class
		 *   那么 getGenericSuperclass(); 获取的是
		 *   		pers.lzy.test.Parent<java.lang.Integer>
		 *   		因为我子类(Son)写的是 public class Son extends Parent<Integer> {}
		 *   		所以他获取的是 pers.lzy.test.Parent<java.lang.Integer>
		 * 2. 如果你 实例化的是此类( new Parent<String>() ) 
		 * 		那么getClass() 必定是 此类也就是Parent的class
		 * 		之后再调用getGenericSuperclass(); 获取的是Object
		 * 		那么抱歉,不用往下执行了,因为你已经不能获取T.class了,
		 *		因为Object上面并没有泛型,你不能往下解析了。
		 *   
		 */
		Type type = this.getClass().getGenericSuperclass();
		
		// 这里  强转成参数化类型:结果跟type一样:
		//					pers.lzy.test.Parent<java.lang.Integer>
		// ParmeterizedType 为 type的子接口
		ParameterizedType ptype = (ParameterizedType) type;
		
		// 获取  实际类型参数(也就是<>里面的类型)
		// 为什么是 数组呢???因为我们<>里面可以有多个, <String, Object>
		// types值为:[class java.lang.Integer]
		Type[] types = ptype.getActualTypeArguments();
		
		// Class 为 Type 的实现类。
		// 我们只要第一个元素,因为我们泛型定义了一个
		// 强转成class。
		// 现在我们就得到了泛型的class(T.class)
		this.clazz = (Class<T>) types[0];
		
	}
	
	/**
	 * 使用clazz
	 * 打印class
	 */
	public void sayClass() {
    
    
		System.out.println(clazz);
	}
}
  • 上面的代码 为啥能 反复强转?反复横跳(滑稽)。请看下面类图
    在这里插入图片描述

3.3.2 Son类代码

/**
 * @author immort(lzy)
 * 注意,这里已经确定了 父类的泛型
 */
public class Son extends Parent<Integer> {
    
    

}

3.3.3 使用

/**
 * 调用类
 * @author immortal
 *
 */
public class Client {
    
    

	public static void main(String[] args) {
    
    
		// 注意,这里一定是实例化的子类
		// 不然肯定得不到T.class
		Parent<Integer> son = new Son();
		son.sayClass();
	}
}

输出的结果

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_42041788/article/details/105886540