Type
只在反射 中才有真正的意义,表示 Java
中所有类型的公共父接口。它包含:原始类型、参数化类型、数组类型、类型变量和基础数据类型。
Java
语言规范中指出变量只有下面三种类型 JLS :
基本类型 primitive types
:boolean, byte, short, int, long, char, float, double
引用类型 reference types
:class, interface, array, type variables
空类型 null type
关于泛型和语言规范中三种类型的关系如下:
如果类或接口声明了类型变量,那么它就是泛型
类和接口如果是泛型,那么它就定义了一个参数化类型,简单理解为泛型就是参数化类型。但是参数化类型是属于类类型或者接口类型的
参数化类型的参数 Type Arguments of Parameterized Types
:可以是引用类型和通配符
在学习 Type
及子接口或实现类时,很容易将它们和语言规范中的类型混淆。语言规范简单来讲类型分为:基本数据类型,类类型(包含接口),数组(另外算上一个类型变量)。总是在想:为什么会多出 Type
这几种类型?它们和基本语言规范中类型的区别是什么呢?实际上从语言规范中的类型来讲,它们是标准的类类型(包含接口),只有在反射解析变量时,它们才有实际的意义,用来区分泛型的几种情景。
类图结构
Type
基本概念Type
的引入主要是为了反射和泛型服务的,它能代表一切类型。在编码使用中(抛开反射概念),这几种类型是标准的类类型和接口类型;它们只能在反射 中才能体现真正的意义,能代表泛型的几种细分场景:
Type
表示 Java
中所有类型的公共接口。也就是反射 中 Type
代表 Java
语言规范中的所有类型。
TypeVariable
表示类型变量,即泛型中的 T, K, V
等等。
ParameterizedType
表示参数化类型,即泛型,如:Collection<String>
。
GenericArrayType
表示数组中的:参数化类型数组,类型变量数组,如:Collection<String>[], T[]
。并不包含基本类型和类类型数组。
WildcardType
表示通配符类型表达式,如 ?
,? extends Number
,? super Integer
。它只是参数化类型中参数的一种类型,无法直接修饰变量。
Class
它是 Type
的实现类,表示除了上面泛型中的几个特定类型之外的所有类型 ,包含基本数据类型,引用类型等。每个类在加载后都会对应一个 Class
类对象,它包含了 .class
文件转换为内存运行时数据结构,也就是包含类中的一切信息。参考:类加载机制
Class
对象是否反射的基石 ,在 Java
中使用 类名.clas
表示类对象。如:String.class, Object.class
等等。
源码分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 public interface Type { default String getTypeName () { return toString(); } } public interface ParameterizedType extends Type { Type[] getActualTypeArguments(); Type getRawType () ; Type getOwnerType () ; } public interface TypeVariable <D extends GenericDeclaration > extends Type , AnnotatedElement { Type[] getBounds(); D getGenericDeclaration () ; String getName () ; AnnotatedType[] getAnnotatedBounds(); } public interface GenericArrayType extends Type { Type getGenericComponentType () ; } public interface WildcardType extends Type { Type[] getUpperBounds(); Type[] getLowerBounds(); } public final class Class <T > implements Serializable , GenericDeclaration , Type , AnnotatedElement {...}
示例 源码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 public class TestType { private void testParameterizedType () { class ParameterizedTypeTestClass { List<String> list; Map.Entry<Integer, String> entry; Class<?> clazz; } showTypeDetails(ParameterizedTypeTestClass.class); } private void testTypeVariable () { class TypeVariableTestClass <K extends Runnable , V > { K k; V v; List<K> list; } showTypeDetails(TypeVariableTestClass.class); } private void testGenericArrayType () { class GenericArrayTypeTestClass <T > { List<String>[] lists; T[] ts; } showTypeDetails(GenericArrayTypeTestClass.class); } private void testWildcardType () { class WildcardTypeTestClass { List<? extends Number> numbers; List<? super Integer> list; } showTypeDetails(WildcardTypeTestClass.class); } private void testAllTypes () { class AllTypes { int i; boolean b; float f; byte [] bytes; String s; Object o; Runnable runnable; Object[] os; } showTypeDetails(AllTypes.class); } private void showTypeDetails (Class<?> clazz) { Field[] fields = clazz.getDeclaredFields(); for (Field field : fields){ System.out.println("*************************" ); System.out.println("showTypeDetails: " + clazz); System.out.println("Field: " + field); Type type = field.getGenericType(); System.out.println("TypeName: " + type.getTypeName()); if (type instanceof ParameterizedType) { ParameterizedType parameterizedType =(ParameterizedType)type; System.out.println("ParameterizedType--RawType: " + parameterizedType.getRawType()); System.out.println("ParameterizedType--OwnerType: " + parameterizedType.getOwnerType()); Type[] types = parameterizedType.getActualTypeArguments(); System.out.println("ParameterizedType--Args.length = " + types.length); for (Type t : types){ System.out.println("ParameterizedType--ActualTypeArguments: " + t); if (t instanceof WildcardType){ WildcardType wildcardType = (WildcardType) t; Type[] uppers = wildcardType.getUpperBounds(); System.out.println("WildcardType--uppers.length = " + uppers.length); for (Type t1 : uppers) { System.out.println("WildcardType--uppers, type =" + t1); } Type[] lowers = wildcardType.getLowerBounds(); System.out.println("WildcardType--lowers.length = " + lowers.length); for (Type t2 : lowers){ System.out.println("WildcardType--lowers. type =" + t2); } } } } else if (type instanceof TypeVariable) { TypeVariable typeVariable = (TypeVariable) type; Type[] types = typeVariable.getBounds(); System.out.println("TypeVariable--Bounds.length = " + types.length); for (Type t : types){ System.out.println("TypeVariable--Bounds = " + t); } System.out.println("TypeVariable--GenericDeclaration = " + typeVariable.getGenericDeclaration()); System.out.println("TypeVariable--Name = " + typeVariable.getName()); } else if (type instanceof GenericArrayType) { GenericArrayType genericArrayType = (GenericArrayType) type; System.out.println("GenericArrayType--ComponentType: " + genericArrayType.getGenericComponentType()); } else if (type instanceof Class) { System.out.println("Class--SimpleName = " + ((Class) type).getSimpleName()); } } } public static void main (String[] args) { TestType testType = new TestType(); testType.testParameterizedType(); testType.testTypeVariable(); testType.testGenericArrayType(); testType.testWildcardType(); } }
源码解析:
反射后的字段类型 只有四种:ParameterizedType, TypeVariable, GenericArrayType, Class
,它们的公共父接口为 Type
。
反射后参数化类型的参数 类型为:通配符 WildcardType
和上面四种类型。 1 2 3 4 5 6 Class<?> clazz; List<? extends Number> numbers; List<List<String>> listList; List<K> listK; List<V[]> listVArray; List<String> list;
结果分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 ************************* // 传入的类名为 TestType 的内部类 1ParameterizedTypeTestClass showTypeDetails: class com.***.TestType$1ParameterizedTypeTestClass // 获取的字段为 list,类型为:参数化类型 List<String>, // 其原始类型为 List,参数为 String Field: java.util.List com.***.TestType$1ParameterizedTypeTestClass.list TypeName: java.util.List<java.lang.String> ParameterizedType--RawType = interface java.util.List ParameterizedType--OwnerType = null ParameterizedType--Args.length = 1 ParameterizedType--ActualTypeArguments = class java.lang.String ************************* showTypeDetails: class com.***.TestType$1ParameterizedTypeTestClass Field: java.util.Map$Entry com.***.TestType$1ParameterizedTypeTestClass.entry TypeName: java.util.Map.java.util.Map$Entry<java.lang.Integer, java.lang.String> ParameterizedType--RawType = interface java.util.Map$Entry ParameterizedType--OwnerType = interface java.util.Map ParameterizedType--Args.length = 2 ParameterizedType--ActualTypeArguments = class java.lang.Integer ParameterizedType--ActualTypeArguments = class java.lang.String ************************* showTypeDetails: class com.***.TestType$1ParameterizedTypeTestClass // 获取的字段为 clazz,类型为:参数化类型 Class<?> Field: java.lang.Class com.***.TestType$1ParameterizedTypeTestClass.clazz TypeName: java.lang.Class<?> ParameterizedType--RawType = class java.lang.Class ParameterizedType--OwnerType = null ParameterizedType--Args.length = 1 ParameterizedType--ActualTypeArguments = ? // 其参数为通配符类型 WildcardType--uppers.length = 1 WildcardType--uppers, type = class java.lang.Object WildcardType--lowers.length = 0 ************************* // 内部类持有外部类的引用 showTypeDetails: class com.***.TestType$1ParameterizedTypeTestClass Field: final com.***.TestType com.***.TestType$1ParameterizedTypeTestClass.this$0 TypeName: com.***.TestType Class--SimpleName = TestType ************************* showTypeDetails: class com.***.TestType$1TypeVariableTestClass // 获取的字段为 k,类型为:类型变量 K Field: java.lang.Runnable com.***.TestType$1TypeVariableTestClass.k TypeName: K TypeVariable--Bounds.length = 1 TypeVariable--Bounds = interface java.lang.Runnable TypeVariable--GenericDeclaration = class com.***.TestType$1TypeVariableTestClass TypeVariable--Name = K ************************* showTypeDetails: class com.***.TestType$1TypeVariableTestClass Field: java.lang.Object com.***.TestType$1TypeVariableTestClass.v TypeName: V TypeVariable--Bounds.length = 1 TypeVariable--Bounds = class java.lang.Object TypeVariable--GenericDeclaration = class com.***.TestType$1TypeVariableTestClass TypeVariable--Name = V ************************* showTypeDetails: class com.***.TestType$1TypeVariableTestClass Field: java.util.List com.***.TestType$1TypeVariableTestClass.list TypeName: java.util.List<K> ParameterizedType--RawType = interface java.util.List ParameterizedType--OwnerType = null ParameterizedType--Args.length = 1 ParameterizedType--ActualTypeArguments = K ************************* showTypeDetails: class com.***. TestType$ 1TypeVariableTestClass Field: final com.***.TestType com.***.TestType$1TypeVariableTestClass.this$0 TypeName: com.***.TestType Class--SimpleName = TestType ************************* showTypeDetails: class com.***.TestType$1GenericArrayTypeTestClass // 获取字段为 lists,类型为:泛型数组 List<String>[] Field: java.util.List[] com.***.TestType$1GenericArrayTypeTestClass.lists TypeName: java.util.List<java.lang.String>[] GenericArrayType--ComponentType = java.util.List<java.lang.String> ************************* showTypeDetails: class com.***.TestType$1GenericArrayTypeTestClass Field: java.lang.Object[] com.***.TestType$1GenericArrayTypeTestClass.ts TypeName: T[] GenericArrayType--ComponentType = T ************************* showTypeDetails: class com.***.TestType$1GenericArrayTypeTestClass Field: final com.***.TestType com.***.TestType$1GenericArrayTypeTestClass.this$0 TypeName: com.***.TestType Class--SimpleName = TestType ************************* showTypeDetails: class com.***.TestType$1WildcardTypeTestClass // 获取字段为 numbers,类型为:参数化类型 // 参数化类型的参数为:通配符 Field: java.util.List com.***.TestType$1WildcardTypeTestClass.numbers TypeName: java.util.List<? extends java.lang.Number> ParameterizedType--RawType = interface java.util.List ParameterizedType--OwnerType = null ParameterizedType--Args.length = 1 ParameterizedType--ActualTypeArguments = ? extends java.lang.Number WildcardType--uppers.length = 1 WildcardType--uppers, type = class java.lang.Number WildcardType--lowers.length = 0 ************************* showTypeDetails: class com.***.TestType$1WildcardTypeTestClass Field: java.util.List com.***.TestType$1WildcardTypeTestClass.list TypeName: java.util.List<? super java.lang.Integer> ParameterizedType--RawType = interface java.util.List ParameterizedType--OwnerType = null ParameterizedType--Args.length = 1 ParameterizedType--ActualTypeArguments = ? super java.lang.Integer WildcardType--uppers.length = 1 WildcardType--uppers, type = class java.lang.Object WildcardType--lowers.length = 1 WildcardType--lowers. type = class java.lang.Integer ************************* showTypeDetails: class com.***.TestType$1WildcardTypeTestClass Field: final com.***.TestType com.***.TestType$1WildcardTypeTestClass.this$0 TypeName: com.***.TestType Class--SimpleName = TestType ************************* // 获取基本数据类型、非泛型数组字段 showTypeDetails: class com.***.TestType$1AllTypes Field: int com.***.TestType$1AllTypes.i TypeName: int Class--SimpleName = int ************************* showTypeDetails: class com.***.TestType$1AllTypes Field: boolean com.***.TestType$1AllTypes.b TypeName: boolean Class--SimpleName = boolean ************************* showTypeDetails: class com.***.TestType$1AllTypes Field: float com.***.TestType$1AllTypes.f TypeName: float Class--SimpleName = float ************************* showTypeDetails: class com.***.TestType$1AllTypes Field: byte[] com.***.TestType$1AllTypes.bytes TypeName: byte[] Class--SimpleName = byte[] ************************* showTypeDetails: class com.***.TestType$1AllTypes Field: java.lang.String com.***.TestType$1AllTypes.s TypeName: java.lang.String Class--SimpleName = String ************************* showTypeDetails: class com.***.TestType$1AllTypes Field: java.lang.Object com.***.TestType$1AllTypes.o TypeName: java.lang.Object Class--SimpleName = Object ************************* showTypeDetails: class com.***.TestType$1AllTypes Field: java.lang.Runnable com.***.TestType$1AllTypes.runnable TypeName: java.lang.Runnable Class--SimpleName = Runnable ************************* showTypeDetails: class com.***.TestType$1AllTypes Field: final com.***.TestType com.***.TestType$1AllTypes.this$0 TypeName: com.***.TestType Class--SimpleName = TestType
参考文档