定义
Type
是java编程语言所有类型的父接口。子类型包括:原始类型Class
,参数化类型ParameterizedType
,数组类型GenericArrayType
,类型变量TypeVariable
和基本类型Class
Type
是Java 编程语言中所有类型的公共高级接口(官方解释),也就是Java中所有类型的“爹”,它并不是我们平常工作中经常使用的 int、String、List、Map等数据类型,而是从Java语言角度来说,对基本类型、引用类型向上的抽象;
public interface Type {
/**
* Returns a string describing this type, including information
* about any type parameters.
*
* @implSpec The default implementation calls {@code toString}.
*
* @return a string describing this type
* @since 1.8
*/
default String getTypeName() {
return toString();
}
}
复制代码
⚠Class也是Type的一种,数组(不是数组类型)、枚举等“类型”是相对Class来说的
Type接口的意义
Type接口说从JDK5开始引入的,主要是为了泛型,没有泛型之前,只有原始类型(Class),即所有的原始类型都是通过Class类进行抽象。Class类的一个具体对象就代表一个指定的类型。泛型出现,也扩充了数据类型。从只有原始类型扩充了参数化类型、类型变量类型、泛型数组类型、这些都是Type的子接口。
为了程序的扩展性,Java引入了Type接口作为Class、ParameterizedType、TypeVariable、GenericArrayTypehe、WildcardType这几种类型的父接口。实现了Type类型参数接受以上五种子类的实参或者返回值类型就是Type类型的参数。
五种类型说明:
Class:对应原始类型和基本类型,原始类型指我们平常所指的 不带类型参数的类接口(非泛型类或者泛型类不带<>)
,注解
,枚举
等结构
ParamterizedType:参数化类型,带有类型参数的类型,即常说的泛型,如:List<String>
、List<?>
、Class<T>
、Map<Integer,String>
等等
TypeVariable:类型变量,对应参数化类型<>里面的T
,E
等等,表示泛指任何类
GenericArrayType:(泛型)数组类型,指数组元素是参数化类型或者类型变量类型的数组类型。例如:T[]
、List<T>[]
、List<String>[]
等等
WildcardType:通配符表达式或泛型表达式,比如[?]
、[? extends T]
、[? super T]
。虽然WildcardType是Type的一个子接口,但并不是Java类型的一种
1、Class 原始或者基本类型
不带类型参数的类接口(非泛型类或者泛型类不带<>)
,注解
,枚举
等结构
测试代码
TypePrintUtil
类代码见附录
public static void main(String[] args) throws NoSuchMethodException {
testRawType();
}
private static void testRawType() throws NoSuchMethodException {
Method rawType = JavaTypeTest.class.getDeclaredMethod("rawType", Object.class, int.class, String.class, int[].class,Enum.class);
TypePrintUtil.printTypeName(rawType);
}
public int rawType(Object p1, int p2, String p3, int[] p4,Enum p5) {
return 0;
}
复制代码
打印结果
开始打印参数类型_____________________________ :
开始打印当前方法第0个参数___________________ :
原始类型或者基本类型【class java.lang.Object】 类型接口【Object】
开始打印当前方法第1个参数___________________ :
原始类型或者基本类型【int】 类型接口【int】
开始打印当前方法第2个参数___________________ :
原始类型或者基本类型【class java.lang.String】 类型接口【String】
开始打印当前方法第3个参数___________________ :
原始类型或者基本类型【class [I】 类型接口【int[]】
开始打印当前方法第4个参数___________________ :
原始类型或者基本类型【class java.lang.Enum】 类型接口【Enum】
开始打印返回值类型____________________________ :
原始类型或者基本类型【int】 类型接口【int】
复制代码
2、ParameterizedType 参数化类型
List<String>
、List<?>
、Class<T>
、Map<Integer,String>
等泛型类或者泛型接口
类型说明
方法:
-
Type[] getActualTypeArguments()
返回一个 Type 对象数组,表示该类型的实际类型参数。(就是返回参数类型<>里的类型参数的类型,因为可能存在多个类型参数,例如Map<K,V>,所以返回的是一个Type数组)无论<>中嵌套几层<>,此方法仅能获取最外层<>中类型参数的类型。 -
Type getOwnerType()
返回Type对象,表示此类型是其成员之一的类型。如果此类型为顶层类型,则返回null -
Type getRawType()
返回Type对象,表示声明此类型的类或者接口。例如List<T>
返回就是List
的类型即Class,简单来说就是返回<>前面的类型。
测试代码
public static void main(String[] args) throws NoSuchMethodException {
testParameterizedType();
}
private static void testParameterizedType() throws NoSuchMethodException {
Method rawType = JavaTypeTest.class.getDeclaredMethod("parameterizedType", List.class, List.class, Test.class);
TypePrintUtil.printTypeName(rawType);
}
public <T> Map<String, T> parameterizedType(List<String> p1, List p2, Test<String> p3) {
return null;
}
public interface Test<T> {
}
复制代码
打印结果
开始打印参数类型_____________________________ :
开始打印当前方法第0个参数___________________ :
ParameterizedType类型【java.util.List<java.lang.String>】 类型接口【ParameterizedType】
ParameterizedType类型,开始打印<>内ActualType类型_____________
开始打印当前方法第0个参数___________________ :
原始类型或者基本类型【class java.lang.String】 类型接口【String】
开始打印当前方法第1个参数___________________ :
原始类型或者基本类型【interface java.util.List】 类型接口【List】
开始打印当前方法第2个参数___________________ :
ParameterizedType类型【com.mumu.type.JavaTypeTest.com.mumu.type.JavaTypeTest$Test<java.lang.String>】 类型接口【ParameterizedType】
ParameterizedType类型,开始打印<>内ActualType类型_____________
开始打印当前方法第0个参数___________________ :
原始类型或者基本类型【class java.lang.String】 类型接口【String】
开始打印返回值类型____________________________ :
ParameterizedType类型【java.util.Map<java.lang.String, T>】 类型接口【ParameterizedType】
ParameterizedType类型,开始打印<>内ActualType类型_____________
开始打印当前方法第0个参数___________________ :
原始类型或者基本类型【class java.lang.String】 类型接口【String】
开始打印当前方法第1个参数___________________ :
TypeVariable类型【T】 类型接口【TypeVariable】
TypeVariable类型【T】 genericDeclaration:【public java.util.Map com.mumu.type.JavaTypeTest.parameterizedType(java.util.List,java.util.List,com.mumu.type.JavaTypeTest$Test)】 bounds:【[class java.lang.Object]】
复制代码
3、TypeVarialbe 类型变量
类型变量,对应参数化类型<>里面的
T
,E
等等,表示泛指任何类
类型说明
方法:
-
Type[] getBounds()
返回表示此类型变量上边界的 Type 对象的数组。注意,如果未显式声明上边界,则上边界为 Object。 -
D getGenericDeclaration()
返回 GenericDeclaration 对象,该对象表示声明此类型变量的一般声明。 -
String getName()
返回此类型变量的名称(T
,E
等等),它出现在源代码中。
测试代码+打印结果
参考ParameterizedType 参数化类型
的测试代码和打印结果,返回值Map<String,T>
中的T的类型即为类型变量类型
4、GenericArray (泛型)数组类型
(泛型)数组类型,指数组元素是【参数化类型或者类型变量类型】的数组类型。例如:
T[]
、List<T>[]
、List<String>[]
等等
类型说明
方法:
Type getGenericComponentType()
返回表示此数组的组件类型的 Type 对象。此方法创建数组的组件类型。获取泛型数组中元素的类型,要注意的是:无论从左向右有几个[]并列,这个方法仅仅脱去最右边的[]之后剩下的内容就作为这个方法的返回值。
测试代码
public static void main(String[] args) throws NoSuchMethodException {
testGenericArrayType();
}
private static void testGenericArrayType() throws NoSuchMethodException {
Method rawType = JavaTypeTest.class.getDeclaredMethod("genericArrayType", Object[].class, List[].class, List[].class);
TypePrintUtil.printTypeName(rawType);
}
public <T> void genericArrayType(T[] p1, List<String>[] p2, List<T>[] p3) {
}
复制代码
打印结果
开始打印参数类型_____________________________ :
开始打印当前方法第0个参数___________________ :
GenericArrayType类型【T】 类型接口【TypeVariable】
开始打印当前方法第1个参数___________________ :
GenericArrayType类型【java.util.List<java.lang.String>】 类型接口【ParameterizedType】
开始打印当前方法第2个参数___________________ :
GenericArrayType类型【java.util.List<T>】 类型接口【ParameterizedType】
开始打印返回值类型____________________________ :
原始类型或者基本类型【void】 类型接口【void】
复制代码
5、WildcardType 通配符(泛型)表达式
通配符表达式或泛型表达式,比如
[?]
、[? extends T]
、[? super T]
。虽然WildcardType是Type的一个子接口,但并不是Java类型的一种
类型说明
方法:
-
Type[] getLowerBounds()
返回表示此类型变量下边界的 Type 对象的数组。注意,如果不存在显式声明的下边界,则下边界为类型 null。在此情况下,将返回长度为零的数组。 -
Type[] getUpperBounds()
返回表示此类型变量上边界的 Type 对象的数组。注意,如果不存在显式声明的上边界,则上边界为 Object。
附录
打印类型帮助类代码
public class TypePrintUtil {
public static void printTypeName(Method method) {
//获取方法的参数类型,按照参数顺序返回一个Type数组,如果没有参照则返回一个长度为0的数组
Type[] genericParameterTypes = method.getGenericParameterTypes();
System.out.println("开始打印参数类型_____________________________ :");
printTypesName(genericParameterTypes, "");
//获取方法返回值的类型
System.out.println("\n开始打印返回值类型____________________________ :");
Type genericReturnType = method.getGenericReturnType();
printTypeName(genericReturnType, "");
}
private static void printTypesName(Type[] genericParameterTypes, String space) {
for (int i = 0; i < genericParameterTypes.length; i++) {
System.out.println(space + "开始打印当前方法第" + i + "个参数___________________ :");
Type genericParameterType = genericParameterTypes[i];
printTypeName(genericParameterType, space);
}
}
private static void printTypeName(Type genericParameterType, String space) {
//类型为原始类型或者基本类型,只指平常所指的类,例如非泛型类,枚举,数组元素类非泛型,注解
if (genericParameterType instanceof Class<?>) {
Class<?> clazz = (Class<?>) genericParameterType;
System.out.println(space + "原始类型或者基本类型【" + clazz + "】\t类型接口【" + clazz.getSimpleName() + "】");
}
//类型为ParameterizedType:如:List<T>、Map<Integer, String>、List<? extends Number> ,自定义泛型类XXX<T>等等
if (genericParameterType instanceof ParameterizedType) {
//获取此类型的实际类型,即<>内的类型,此方法仅获取第一层的类型,如果是List<List<T>>这种还需要在获取一次,才能得到T
ParameterizedType parameterizedType = (ParameterizedType) genericParameterType;
//打印类型
System.out.println(space + "ParameterizedType类型【" + parameterizedType + "】\t类型接口【" + parameterizedType.getClass().getInterfaces()[0].getSimpleName() + "】");
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
System.out.println(space + "ParameterizedType类型,开始打印<>内ActualType类型_____________");
printTypesName(actualTypeArguments, " ");
}
//类型为GenericArrayType: 比如List<T>[],T[]这种。注意,这不是我们说的一般数组,而是表示一种【元素类型是参数化类型或者类型变量的】数组类型
else if (genericParameterType instanceof GenericArrayType) {
GenericArrayType genericArrayType = (GenericArrayType) genericParameterType;
//返回表示此数组的组件类型的 Type 对象
Type genericComponentType = genericArrayType.getGenericComponentType();
System.out.println(space + "GenericArrayType类型【" + genericComponentType + "】\t类型接口【" + genericComponentType.getClass().getInterfaces()[0].getSimpleName() + "】");
}
//类型为TypeVariable: 如参数类型中T,E等类型变量,泛指任何类型
else if (genericParameterType instanceof TypeVariable) {
TypeVariable typeVariable = (TypeVariable) genericParameterType;
Type[] bounds = typeVariable.getBounds();
GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration();
System.out.println(space + "TypeVariable类型【" + typeVariable + "】\t类型接口【" + typeVariable.getClass().getInterfaces()[0].getSimpleName() + "】");
System.out.println(space + "TypeVariable类型【" + typeVariable + "】\tgenericDeclaration:【" + genericDeclaration + "】\tbounds:【" + Arrays.toString(bounds) + "】");
}
//WildcardType 通配符表达式,例如:【?】【? super T】【? extends T】,虽然WildcardType是Type的一个子接口,但并不是Java类型中的一种
else if (genericParameterType instanceof WildcardType) {
WildcardType wildcardType = (WildcardType) genericParameterType;
System.out.println(space + "WildcardType类型【" + wildcardType + "】\t类型接口【" + wildcardType.getClass().getInterfaces()[0].getSimpleName() + "】");
}
}
}
复制代码