java 泛型

jdk 1.5之前没有泛型。
jdk 1.5开始,增加了一系列泛型相关的接口和类:其中两个顶级接口是TypeAnnotatedElement

Type和Class的区别

在jdk 1.5之前,一个类型用一个Class对象表示,一个类型必对应一个Class对象,一个Class对象代表一个类型。

在jdk 1.5之后,一个泛型类还会对应一个ParameterizedType对象(例如Collection),其类型化参数会用一个TypeVariable对象表示,而通配符类型化的参数则会用一个WildcardType(<? super T>)对象表示,一个泛型方法的类型化参数也是如此。泛型方法的返回值或参数的类型可能会对应着一个ParameterizedType对象(Comparator<? super T>)、也可能对应着一个GenericArrayType对象(T[])。以上新增的类型都是为了支持泛型。

jdk对泛型的支持是在编译阶段实现的。在编译阶段,会为带有类型参数的类、方法生成相应的Type类型信息字节码,编译到相应的class文件中。

以JDK中的Arrays类中的一个sort方法为例:

 public static <T> void sort(T[] a, Comparator<? super T> c) {
        if (c == null) {
            sort(a);
        } else {
            if (LegacyMergeSort.userRequested)
                legacyMergeSort(a, c);
            else
                TimSort.sort(a, 0, a.length, c, null, 0, 0);
        }
    }

在上例方法中,sort的参数有两个:

  • 参数a的类型T[],在jdk中,这个类型就是一个GenericArrayType类型。
  • 参数c的类型Comparator<? super T>,就是一个ParameterizedType类型。

而在方法的返回类型void之前,还定义了一个,这个就是一个TypeVariable类型。
同样,对于参数c的类型Comparator<? super T>,这里<? super T>则是一个WildcardType类型。

JDK泛型就是给类和方法加上了一个或者多个变量作为参数,而这样的变量的特殊之处在于:它代表的是一个类型,而不是一个对象。因此,
如:Collection<E>中,E是一个变量,作为一个参数,这个参数的值可以是任何类型,比如类型String、或者类型Thread
JDK泛型设计中:

  • 称带参数的类为参数化类型,即ParameterizedType
  • 称类的参数为参数变量,即TypeVariable
  • 如果参数化类型作为某个方法的参数时,使用了通配符<? extends T>类似的,称这种参数为通配符类型,即WildCardType
  • 称参数变量构成的数组为泛型数组类型:即GenericArrayType

Type的四个子接口的用途

  • GenericArrayType类型的实例对象只可能是表示 方法参数的类型 \ 返回值的类型 \ 字段的类型 ,不可能是表示某个泛型类或接口(即参数化类型)
  • ParameterizedType类型的实例对象,可能是表示某个泛型类或接口(即参数化类型),也可能是表示某个字段的类型 或 某个方法参数的类型
  • WildCardType类型的对象,只能是表示 方法参数的类型的参数 这一种用途。
  • TypeVariable类型的对象,则可以表示 泛型类或接口的参数,或者方法返回值类型参数,或者字段的类型参数,或者方法参数的类型参数

获得泛型信息的一些方法

获得某个泛型类的类型参数信息

Class类的方法:TypeVariable<?>[] getTypeParameters,就能获得一个泛型类或者泛型接口的的类型参数信息。
如果类class不是泛型类,则返回一个length=0的TypeVariable<?>[]数组。
示例:

package org.glyptodon.guacamole.environment;

import java.lang.reflect.TypeVariable;
import java.util.Collection;
import java.util.Comparator;

public class Test {
	public static void main(String[] args) {
		
		TypeVariable<Class<Comparator>>[] typeVariables = Comparator.class.getTypeParameters();
		for (TypeVariable<Class<Comparator>> typeVariable : typeVariables) {
			System.out.println(typeVariable.getName());		// T ,类型参数的变量的变量名
			System.out.println(typeVariable.getBounds()[0]);// class java.lang.Object, 类型参数的限定(比如<E extends Iterable>,如果没有限定,则默认为  Object类)
			System.out.println(typeVariable.getClass());	// class sun.reflect.generics.reflectiveObjects.TypeVariableImpl, typeVariable对象的class
			System.out.println(typeVariable.getTypeName());	// T 
		}
	}
}

获得某个方法的泛型信息

  • Method类的Type[] getTypeParameters()方法,可以获取方法的所有类型参数的相应的类型构成的对象数组。如果方法不是泛型方法,则返回一个length=0的数组,如果方法有两个类型参数,则泛型数组的length=2。
    例如:
import java.lang.reflect.Method;
import java.lang.reflect.TypeVariable;
import java.util.Arrays;

public class Test {
	public static void main(String[] args) throws NoSuchFieldException, SecurityException {
		Method[] methods = Arrays.class.getDeclaredMethods();
		for (Method method : methods) {
			if(method.getTypeParameters().length>0) {
				System.out.println(method.toGenericString());
				TypeVariable<Method>[] methodTypeParams = method.getTypeParameters();
				for (TypeVariable<Method> typeVariable : methodTypeParams) {
					System.out.println(typeVariable.getName());		
					System.out.println(typeVariable.getBounds()[0]);
					System.out.println(typeVariable.getClass());	
					System.out.println(typeVariable.getTypeName());	 
					System.out.println("\n-------------------------\n");
				}
				
			}
		}
	}
}

一些输出结果:


public static <T> void java.util.Arrays.sort(T[],java.util.Comparator<? super T>)
T
class java.lang.Object
class sun.reflect.generics.reflectiveObjects.TypeVariableImpl
T

-------------------------

public static <T> void java.util.Arrays.parallelSort(T[],int,int)
T
java.lang.Comparable<? super T>
class sun.reflect.generics.reflectiveObjects.TypeVariableImpl
T


  • Method类的Type[] getTypeParameters()方法,可以获取方法的所有类型参数的相应的类型构成的对象数组。如果方法不是泛型方法,则返回一个length=0的数组,如果方法有两个类型参数,则泛型数组的length=2。
    例如:
import java.lang.reflect.Method;
import java.lang.reflect.TypeVariable;
import java.util.Arrays;

public class Test {
	public static void main(String[] args) throws NoSuchFieldException, SecurityException {
		Method[] methods = Arrays.class.getDeclaredMethods();
		for (Method method : methods) {
			if(method.getTypeParameters().length>0) {
				System.out.println(method.toGenericString());
				TypeVariable<Method>[] methodTypeParams = method.getTypeParameters();
				for (TypeVariable<Method> typeVariable : methodTypeParams) {
					System.out.println(typeVariable.getName());		
					System.out.println(typeVariable.getBounds()[0]);
					System.out.println(typeVariable.getClass());	
					System.out.println(typeVariable.getTypeName());	 
					System.out.println("\n-------------------------\n");
				}
				
			}
		}
	}
}

一些输出结果:


public static <T> void java.util.Arrays.sort(T[],java.util.Comparator<? super T>)
T
class java.lang.Object
class sun.reflect.generics.reflectiveObjects.TypeVariableImpl
T

-------------------------

public static <T> void java.util.Arrays.parallelSort(T[],int,int)
T
java.lang.Comparable<? super T>
class sun.reflect.generics.reflectiveObjects.TypeVariableImpl
T

  • Method类的Type getGenericReturnType()方法,可以获取方法的返回值的泛型信息。如果方法的返回值类型是泛型的,那么用于表示方法的返回值的类型的对象,要么是GenericArrayType的实例对象(返回值定义形如T[])、要么是ParameterizedType的实例对象(返回值定义如:List<T>)
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.Arrays;
import java.util.stream.Collectors;

public class Test {
	public static void main(String[] args) throws NoSuchFieldException, SecurityException {
		Method[] methods = Collectors.class.getDeclaredMethods();
		for (Method method : methods) {
			Type returnType = method.getGenericReturnType();
			if(!(returnType instanceof Class)) {
				
				if(returnType instanceof GenericArrayType) {
					System.out.println(method.toGenericString());
					System.out.println(returnType.getClass());
					GenericArrayType genericArrayType = (GenericArrayType) returnType;
					System.out.println(genericArrayType.getTypeName());
					System.out.println(genericArrayType.getGenericComponentType());
					/** 输出示例:
					 * public static <T> T[] java.util.Arrays.copyOf(T[],int) 
					 * class sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl 
					 * T[] 
					 * T
					 */
				}
				if(returnType instanceof ParameterizedType) {
					System.out.println("方法的全限定名称:"+method.toGenericString());
					System.out.println("用于表示方法的返回值类型的对象,的全限定类名:"+returnType.getClass());
					ParameterizedType parameterizedType = (ParameterizedType) returnType;
					System.out.println(parameterizedType.getOwnerType());
					System.out.println(parameterizedType.getRawType());
					System.out.println(parameterizedType.getTypeName());
					Type[] typeArguments = parameterizedType.getActualTypeArguments();
					for (Type type : typeArguments) {
						System.out.println("用于表示方法的返回值类型的类型参数的对象,所属的类:"+type.getClass());
						if(type instanceof WildcardType ) {
							WildcardType wildcardTypeArgument = ((WildcardType)type);
							System.out.println("用于表示方法的返回值类型的类型参数的对象,是WildcardType类型的:"+wildcardTypeArgument.toString());
							String upperBoundsTypes;
							if((upperBoundsTypes=Arrays.toString(wildcardTypeArgument.getUpperBounds())).length()>2) {
								
								System.out.println(" 通配符类型的类型参数的父类: "+upperBoundsTypes.substring(1, upperBoundsTypes.length()-1));
							}
							String lowerBoundsTypes;
							if((lowerBoundsTypes = Arrays.toString(wildcardTypeArgument.getLowerBounds())).length()>2) {
								System.out.println(" 通配符类型的类型参数的子类: "+ lowerBoundsTypes.substring(1,lowerBoundsTypes.length()-1));
							}
							
						}
						if(type instanceof GenericArrayType) {
							System.out.println("用于表示方法的返回值类型的类型参数的对象,是GenericArrayType类型的:"+(GenericArrayType)type);
							
						}
						if(type instanceof ParameterizedType) {
							System.out.println("用于表示方法的返回值类型的类型参数的对象,是ParameterizedType类型的:"+(ParameterizedType)type);
							
						}
						if(type instanceof TypeVariable) {
							System.out.println("用于表示方法的返回值类型的类型参数的对象,是TypeVariable类型的:"+(TypeVariable)type);
							String boundsTypes;
							if((boundsTypes=Arrays.toString(((TypeVariable)type).getBounds())).length()>2) {
								
								System.out.println(" 类型变量的类型参数的父类: "+boundsTypes.substring(1, boundsTypes.length()-1));
							}
						}
					}
					/**
					 * 输出示例:
					 * public static <T> java.util.List<T> java.util.Arrays.asList(T...) class
					 * sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl 
					 * T 
					 * null 
					 * interface java.util.List 
					 * java.util.List<T>
					 */
				}
								
				System.out.println("");
			}
		}
	}
	
}
  • Method类的方法Type[] getGenericParameterType(),可以获取方法参数的类型对象的泛型信息。如果方法参数的类型是泛型,则表示方法参数的类型的对象要么是GenericArrayType(即泛型数组)的实例对象、要么是ParameterizedType(参数化类型)的实例对象。
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.Arrays;

public class Test {
	public static void main(String[] args) throws NoSuchFieldException, SecurityException {
		Method[] methods = Arrays.class.getDeclaredMethods();
		for (Method method : methods) {
			if(method.getTypeParameters().length>0) {
				Type[] genericParameterTypes = method.getGenericParameterTypes();
				for (Type genericParameterType : genericParameterTypes) {
					if(!(genericParameterType instanceof Class)) {
						if(genericParameterType instanceof GenericArrayType) {
							GenericArrayType genericArrayType  = (GenericArrayType) genericParameterType;
							System.out.println("方法的全限定声明:"+method.toGenericString());
							System.out.println("方法参数的类型对象的类信息:"+genericArrayType.getClass());
							System.out.println("方法参数的类型对象的全限定名称:"+genericArrayType.getTypeName());
							System.out.println(genericArrayType.toString());
							System.out.println(genericArrayType.getGenericComponentType());
						}
						
					}
						System.out.println();
						if(genericParameterType instanceof ParameterizedType) {
							ParameterizedType parameterizedType  = (ParameterizedType) genericParameterType;
							System.out.println("方法的全限定声明:"+method.toGenericString());
							System.out.println("方法参数的类型对象的类信息:"+parameterizedType.getClass());
							System.out.println("方法参数的类型对象的全限定名称:"+parameterizedType.getTypeName());
							System.out.println(parameterizedType.toString());
							Type[] typeArguments = parameterizedType.getActualTypeArguments();
							for (Type type : typeArguments) {
								System.out.println("方法参数的类型的类型参数的类型:"+type.getClass());
								if(type instanceof WildcardType) {
									WildcardType wildcardTypeArgument = (WildcardType) type;
									System.out.println("方法参数的类型的类型参数信息:"+wildcardTypeArgument.getTypeName());
									String upperBoundsTypes;
									if((upperBoundsTypes=Arrays.toString(wildcardTypeArgument.getUpperBounds())).length()>2) {
										
										System.out.println(" 方法参数的类型的类型参数的父类: "+upperBoundsTypes.substring(1, upperBoundsTypes.length()-1));
									}
									String lowerBoundsTypes;
									if((lowerBoundsTypes = Arrays.toString(wildcardTypeArgument.getLowerBounds())).length()>2) {
										System.out.println(" 方法参数的类型的类型参数的子类: "+ lowerBoundsTypes.substring(1,lowerBoundsTypes.length()-1));
									}
									
								}
								if(type instanceof TypeVariable) {
									TypeVariable<Class> typeVariableArgument = (TypeVariable<Class>) type;
									System.out.println("方法参数的类型的类型参数信息:"+typeVariableArgument.getTypeName());
									String upperBoundsTypes;
									if((upperBoundsTypes=Arrays.toString(typeVariableArgument.getBounds())).length()>2) {
										
										System.out.println(" 类型参数的父类: "+upperBoundsTypes.substring(1, upperBoundsTypes.length()-1));
									}
								}
							}
							
							System.out.println(parameterizedType.getOwnerType());
							System.out.println(parameterizedType.getRawType());
						}
						
				}
				System.out.println("\n");
			
			}
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值