关于泛型、反射问题

立青_ 中级 2020-08-17 02:18:48
有个超类、子类、孙子类,我在子类中指明了泛型,结果在运行孙子类时,超类无法解析泛型,Type不能强制转换ParameterizedType,把泛型放在孙子类就是正常的。怎么解决?
...全文
8966 1 打赏 收藏 举报
写回复
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
Eshel 2020-08-18
A 类是超类, B 类继承A类, C类继承B类, 你是想获取B类上的 String 吧 如果是的话可以用下边的方法:

	public static class A<T>{}

	public static class B<I> extends A<String> {}

	public static class C extends B<Integer> {}
   
	//... 在 main 方法中
	C c = new C();
	//String.class
	Class clazz = ReflectionUtil.getGenericClassSupportInterface(c.getClass(), A.class, 0);
	//Integer.class
	Class claz2 = ReflectionUtil.getGenericClassSupportInterface(c.getClass(), B.class, 0);


public class ReflectionUtil {

	/**
	 * ## 支持获取接口泛型
	 * owner: A.class, target: B.class
	 * 获取类B上声明的第 index 个泛型的在 类 A 中的实际类型
	 * @param owner (子类)泛型的拥有者
	 * @param index target声明的位置从左到右数第 index 个泛型 如泛型<A, B> A对应index=1, B对应index=2
	 * @param target (父类)声明泛型的类, target 必须是 owner 的父类
	 * 例如:
	 *      class<T> B{
	 *          public Class getGenericClass(){
	 *               return ReflectHelper.getGenericClass(getClass(), B.class, 0);
	 *          }
	 *      }
	 *      class A extends B<String>{
	 *
	 *      }
	 *      class C extends B<Integer>{
	 *
	 *      }
	 *      class D<A> extends B<A>{
	 *
	 *      }
	 *
	 *     System.out.println(new A().getGenericClass() instanceOf String.class);
	 *     System.out.println(new C().getGenericClass() instanceOf Integer.class);
	 *     System.out.println(new D<Double>().getGenericClass() instanceOf Double.class);
	 *     打印结果为:
	 *               true
	 *               true
	 *               false
	 */
	public static<T> Class getGenericClassSupportInterface(@NonNull Class<? extends T> owner, @NonNull Class<T> target, int index){

		if(owner == target)
			return null;

		if(!target.isAssignableFrom(owner))
			return null;

		TypeVariable<Class<T>>[] tps = target.getTypeParameters();
		if(index >= tps.length)
			return null;

		class Cache{

			private Cache(Class clazz) {
				this.clazz = clazz;
			}

			private Cache(Class clazz, int index) {
				this.clazz = clazz;
				this.index = index;
			}

			@NonNull
			@Override
			public String toString() {
				return clazz.getName() + "-@-" + index;
			}

			private Class clazz;
			private int index = 0;
		}

		LinkedList<Cache> classes = new LinkedList<>();
		classes.add(new Cache(owner));
		Class nextClazz = owner;

		outside:
		while (true){
			Class superClazz = nextClazz.getSuperclass();
			if(superClazz == target)
				break;
			if(superClazz != null && target.isAssignableFrom(superClazz)){
				classes.add(new Cache(superClazz));
			}else {
				Class[] interfaces = nextClazz.getInterfaces();
				for (int i = 0; i < interfaces.length; i++) {
					Class interfaca = interfaces[i];
					if(interfaca == target)
						break outside;
					if(target.isAssignableFrom(interfaca)){
						classes.add(new Cache(interfaca, i));
						superClazz = interfaca;
						break;
					}
				}
			}
			nextClazz = superClazz;
			if(superClazz == null)
				break;
		}

		Cache cache = classes.removeLast();
		Class supClazz = cache.clazz;

		Type typeVar;
		Class last = target;
		if(last.isInterface()){
			typeVar = ((ParameterizedType) supClazz.getGenericInterfaces()[cache.index]).getActualTypeArguments()[index];
		}else {
			typeVar = ((ParameterizedType) supClazz.getGenericSuperclass()).getActualTypeArguments()[index];
		}

		if(typeVar instanceof Class)
			return (Class) typeVar;

		if(typeVar instanceof ParameterizedType){
			Type rawType = ((ParameterizedType) typeVar).getRawType();
			if(rawType instanceof Class){
				return (Class) rawType;
			}
		}

		while (!classes.isEmpty()) {
			System.out.println(cache);
			index = Util.indexOf(supClazz.getTypeParameters(), typeVar, new Util.Comparator<TypeVariable, Type>() {
				@Override
				public boolean equals(TypeVariable left, Type right) {
					if(left == right)
						return true;

					if(left == null || right == null)
						return false;

					if(!(right instanceof TypeVariable))
						return false;

					String leftName = left.getName();
					String rightName = ((TypeVariable) right).getName();

					return leftName.equals(rightName);
				}
			});
			last = supClazz;
			cache = classes.removeLast();
			supClazz = cache.clazz;
			System.out.println(cache + "___");
			if(last.isInterface()){
				typeVar = ((ParameterizedType) supClazz.getGenericInterfaces()[cache.index]).getActualTypeArguments()[index];
			}else {
				typeVar = ((ParameterizedType) supClazz.getGenericSuperclass()).getActualTypeArguments()[index];
			}
			if(typeVar instanceof Class)
				return (Class) typeVar;
		}
		return null;
	}

	static class Util{
		//获取数组 array 中 object 的角标
		public static <L, R> int indexOf(L[] array, R object, @NonNull Comparator<L, R> comparator) {
			if (array == null)
				return -1;
			for (int i = 0; i < array.length; i++) {
				if (comparator.equals(array[i], object))
					return i;
			}
			return -1;
		}

		interface Comparator<L, R> {
			boolean equals(L left, R right);
		}
	}
}
  • 打赏
  • 举报
回复
相关推荐
发帖
Android
加入

7.9w+

社区成员

移动平台 Android
社区管理员
  • Android
  • wresource
  • 帅次
申请成为版主
帖子事件
创建了帖子
2020-08-17 02:18
社区公告
暂无公告