Retrofit完全解析(三):Type<基础详解>
2016-11-14 16:12
295 查看
Object跟Class可跳过
Object
Object是class层次结构的根(Java中万物皆对象)。Object是所有class的超类(包括Class类)。 所有对象,包括数组,实现Object类的(hashCode、equals、clone、toString、notify..)方法。
Class
class的实例Class代表java程序中正在运行的classes和interfaces。
enum和annotation也是一种interface。
每个数组也属于一个class,反射为共享数据类型、大小的Class对象。
原始Java类型(boolean byte char short int long float double)关键字void也可以表示为Class对象。
Class没有公开的构造函数,相反,Class 对象是在加载类时由 Java 虚拟机通过调用类加载器中的 defineClass 方法自动构造的。
Class.class也是一种class。
每个class都有一个相应的Class对象。当类加载器夹在.class文件的时候就会自动创建对应的Class对象,用于表示这个类的类型信息。
Class用来表示class的信息:包命、父类、接口、字段、方法、构造器、注解等。反射中常利用这些信息,可以对于任意一个对象,都能够调用它的任意一个方法,可以于运行时加载、探知、使用编译期间完全未知的classes,生成其对象实体、或对其fields设值、或唤起其methods。
Class实现了Type空接口,Class为原始类型(raw types)
GenericDeclaration
注解:A common interface for all entities that declare type variables.
中文:所有声明类型变量的实体的通用接口。
该接口用来定义哪些对象上是可以声明(定义)范型变量。
目前实现GenericDeclaration接口的类包括Class, Method, Constructor,也就是说只能在这几种对象上进行范型变量的声明(定义)。GenericDeclaration的接口方法getTypeParameters用来逐个获取该GenericDeclaration的范型变量声明。
中文:Type是Java编程语言中所有Type的共同超级接口。 这些包括原始类型(raw types对应Class)、参数化类型(parameterized types对应ParameterizedType)、 数组类型(array types对应GenericArrayType)、 类型变量(type variables对应TypeVariable)和基本类型(primitive types对应Class)。
子接口:ParameterizedType, TypeVariable, GenericArrayType, WildcardType。
实现类:Class(原始类型: raw types)。
ParameterizedType (
ParameterizedType表示参数化类型,例如
注解:返回声明此类型的类或者接口对象
俗解:返回承载该泛型信息的对象, 如上面那个
Type[] getActualTypeArguments():
注解:返回表示此类型的实际类型参数的类型对象数组。
俗解:返回实际泛型类型列表, 如
Type getOwnerType():
注解:返回(本身Type的)父Type对象,比如:如果本身Type是
俗解:返回拥有者(主人).(上面那两个最常用)
举个getOwnerType()的例子:
TypeVariable (
TypeVariable中的D是extends GenericDeclaration的,用来通过范型变量反向获取拥有这个变量的GenericDeclaration。
注解:返回此类型变量的上边界的Type数组(可能有多个),如果上限没有显示声明,则上限为Object。如果上限是ParameterizedType或者TypeVariable,继续创建,如果不是——则中断。
俗解:获取类型变量的上边界, 若未明确声明上边界则默认为Object
D getGenericDeclaration():
注解:返回表示声明此类型变量的通用声明的GenericDeclaration对象。返回为此类型变量声明的通用声明。(类似ParameterizedType的getRawType)
俗解:获取声明该类型变量实体
String getName():
注解:返回此类型变量的名称,如同源代码中出现的。(如上文中的T)
俗解:获取在源码中定义时的名字
注意
类型变量在定义的时候只能使用extends进行(多)边界限定, 不能用super(奇怪的现象,望告知)。
为什么边界是一个数组? 因为类型变量可以通过&进行多个上边界限定,因此上边界有多个
俗解:范型数组,组成数组的元素中有范型则实现了该接口; 它的组成元素是ParameterizedType或TypeVariable类型,它只有一个方法:
注解:返回表示此数组的组件类型的Type对象,此方法创建数组的组件类型.
俗解:返回数组的组成对象, 即被JVM编译后实际的对象
注解:返回表示此类型上限的类型数组。 默认上限是Object。
Type[] getLowerBounds();
注解:返回表示此类型变量的下限的Type对象的数组。 注意,如果没有明确声明下界,下界是null的类型。 在这种情况下,返回零长度数组。
注意:现阶段通配符只接受一个上边界或下边界, 返回数组是为了以后的扩展, 实际上现在返回的数组的大小是1
小结:
ParameterizedType的getActualTypeArguments获取的Tyep不是TypeVariable就是WildcardType
GenericArrayType的getGenericComponentType不是ParameterizedType就是TypeVariable
包含泛型的变量类型才会是四大Type,不然则为Class
四大Type类型 instanceof Class均为false
然而有些Type instanceof Class为true:
ParameterizedType 的getRawType、getActualTypeArguments、getOwnerType;TypeVariable的getBounds;WildcardType的getUpperBounds、getLowerBounds他们获取的Type中如果不包含泛型,则均为Class类型
综上所属,Java中所有Type对象:
1. Type对象 instanceof Object均为true
2. Type对象包含泛型 instanceof Classs 为false,为四大Type之一
3. Type对象不包含泛型 instanceof Classs 为true,不是四大Type,而是接口Type类型。
参考文章:
详解Java泛型type体系整理
Java类型中ParameterizedType,GenericArrayType,TypeVariabl,WildcardType详解
Java Type详解
Java中的Type详解
Object
Object是class层次结构的根(Java中万物皆对象)。Object是所有class的超类(包括Class类)。 所有对象,包括数组,实现Object类的(hashCode、equals、clone、toString、notify..)方法。
Class
class的实例Class代表java程序中正在运行的classes和interfaces。
enum和annotation也是一种interface。
每个数组也属于一个class,反射为共享数据类型、大小的Class对象。
原始Java类型(boolean byte char short int long float double)关键字void也可以表示为Class对象。
Class没有公开的构造函数,相反,Class 对象是在加载类时由 Java 虚拟机通过调用类加载器中的 defineClass 方法自动构造的。
Class.class也是一种class。
每个class都有一个相应的Class对象。当类加载器夹在.class文件的时候就会自动创建对应的Class对象,用于表示这个类的类型信息。
Class用来表示class的信息:包命、父类、接口、字段、方法、构造器、注解等。反射中常利用这些信息,可以对于任意一个对象,都能够调用它的任意一个方法,可以于运行时加载、探知、使用编译期间完全未知的classes,生成其对象实体、或对其fields设值、或唤起其methods。
Class实现了Type空接口,Class为原始类型(raw types)
GenericDeclaration
注解:A common interface for all entities that declare type variables.
中文:所有声明类型变量的实体的通用接口。
该接口用来定义哪些对象上是可以声明(定义)范型变量。
目前实现GenericDeclaration接口的类包括Class, Method, Constructor,也就是说只能在这几种对象上进行范型变量的声明(定义)。GenericDeclaration的接口方法getTypeParameters用来逐个获取该GenericDeclaration的范型变量声明。
初识Type
Type
注解:Type is the common superinterface for all types in the Java programming language. These include raw types, parameterized types, array types, type variables and primitive types.中文:Type是Java编程语言中所有Type的共同超级接口。 这些包括原始类型(raw types对应Class)、参数化类型(parameterized types对应ParameterizedType)、 数组类型(array types对应GenericArrayType)、 类型变量(type variables对应TypeVariable)和基本类型(primitive types对应Class)。
子接口:ParameterizedType, TypeVariable, GenericArrayType, WildcardType。
实现类:Class(原始类型: raw types)。
Type四大子接口
ParameterizedType (Collection<String>
)(参数话类型)
类注解:参数化类型在第一次由反射方法需要时创建,当参数化类型p被创建时,p实例化的通用类型声明被解析,并且递归地创建p的所有类型参数。 重复创建参数化类型不起作用。实现此接口的类的实例必须实现equals()方法,等同于任何两个实例共享同一通用类型声明并具有相等类型参数。
ParameterizedType表示参数化类型,例如
Collection<String>。
方法
Type getRawType():注解:返回声明此类型的类或者接口对象
俗解:返回承载该泛型信息的对象, 如上面那个
Collection<String>承载范型信息的对象是Collection
Type[] getActualTypeArguments():
注解:返回表示此类型的实际类型参数的类型对象数组。
俗解:返回实际泛型类型列表, 如
Map<String, String> map实际范型列表中有两个元素, 都是String
Type getOwnerType():
注解:返回(本身Type的)父Type对象,比如:如果本身Type是
O<T>.I<S>则返回
O<T>,如果此类型是顶级类型,则返回null。
俗解:返回拥有者(主人).(上面那两个最常用)
public class ParameterizedTypeTest { Map<String, String> map; public static void main(String[] args) throws Exception { Field f = TestType.class.getDeclaredField("map"); System.out.println(f.getGenericType()); // java.util.Map<java.lang.String, java.lang.String> System.out.println(f.getGenericType() instanceof ParameterizedType); // true ParameterizedType pType = (ParameterizedType) f.getGenericType(); System.out.println(pType.getRawType()); // interface java.util.Map for (Type type : pType.getActualTypeArguments()) { System.out.println(type); // 打印两遍: class java.lang.String } System.out.println(pType.getOwnerType()); // null } }
举个getOwnerType()的例子:
public static void main(String[] args) throws Exception { Method method = new Test().getClass().getMethod("applyMethod",Map.Entry.class); Type[] types = method.getGenericParameterTypes(); ParameterizedType pType = (ParameterizedType)types[0]; System.out.println(pType.getOwnerType());//打印结果是interface java.util.Map } public static <T,U> void applyMethod(Map.Entry<T,U> mapEntry){ }
TypeVariable (<T>
)(类型变量)
public interface TypeVariable<D extends GenericDeclaration> extends Type {...}
TypeVariable中的D是extends GenericDeclaration的,用来通过范型变量反向获取拥有这个变量的GenericDeclaration。
方法
Type[] getBounds():注解:返回此类型变量的上边界的Type数组(可能有多个),如果上限没有显示声明,则上限为Object。如果上限是ParameterizedType或者TypeVariable,继续创建,如果不是——则中断。
俗解:获取类型变量的上边界, 若未明确声明上边界则默认为Object
D getGenericDeclaration():
注解:返回表示声明此类型变量的通用声明的GenericDeclaration对象。返回为此类型变量声明的通用声明。(类似ParameterizedType的getRawType)
俗解:获取声明该类型变量实体
String getName():
注解:返回此类型变量的名称,如同源代码中出现的。(如上文中的T)
俗解:获取在源码中定义时的名字
注意
类型变量在定义的时候只能使用extends进行(多)边界限定, 不能用super(奇怪的现象,望告知)。
为什么边界是一个数组? 因为类型变量可以通过&进行多个上边界限定,因此上边界有多个
public class TestType <K extends Comparable & Serializable, V> { K key; V value; public static void main(String[] args) throws Exception { // 获取字段的类型 Field fk = TestType.class.getDeclaredField("key"); Field fv = TestType.class.getDeclaredField("value"); Assert.that(fk.getGenericType() instanceof TypeVariable, "必须为TypeVariable类型"); Assert.that(fv.getGenericType() instanceof TypeVariable, "必须为TypeVariable类型"); TypeVariable keyType = (TypeVariable)fk.getGenericType(); TypeVariable valueType = (TypeVariable)fv.getGenericType(); // getName 方法 System.out.println(keyType.getName()); // K System.out.println(valueType.getName()); // V // getGenericDeclaration 方法 System.out.println(keyType.getGenericDeclaration()); // class com.test.TestType System.out.println(valueType.getGenericDeclaration()); // class com.test.TestType // getBounds 方法 System.out.println("K 的上界:"); // 有两个 for (Type type : keyType.getBounds()) { // interface java.lang.Comparable System.out.println(type); // interface java.io.Serializable } System.out.println("V 的上界:"); // 没明确声明上界的, 默认上界是 Object for (Type type : valueType.getBounds()) { // class java.lang.Object System.out.println(type); } } }
GenericArrayType(通用数组类型)
注解:GenericArrayType 表示一种数组类型,其组件类型为参数化类型或类型变量。俗解:范型数组,组成数组的元素中有范型则实现了该接口; 它的组成元素是ParameterizedType或TypeVariable类型,它只有一个方法:
方法
Type getGenericComponentType():注解:返回表示此数组的组件类型的Type对象,此方法创建数组的组件类型.
俗解:返回数组的组成对象, 即被JVM编译后实际的对象
public static void main(String[] args) { new GenericArrayTypeTest(); Method method = Test.class.getDeclaredMethods()[0]; Type[] types = method.getGenericParameterTypes(); for (Type type : types) { if (type instanceof GenericArrayType) { GenericArrayType arrayType = (GenericArrayType) type; System.out.println(type.getTypeName()); Type anyType = arrayType.getGenericComponentType(); printType(anyType); } } } public static void printType(Type type){ String printStr = ""; if (type instanceof GenericArrayType) { printStr = "GenericArrayType"; }else if(type instanceof ParameterizedType){ printStr = "ParameterizedType"; }else if(type instanceof TypeVariable){ printStr = "TypeVariable"; }else if(type instanceof WildcardType){ printStr = "WildcardType"; }else if(type instanceof Class){ printStr = "Class"; }else{ printStr = "UnKnown"; } System.out.println(type.getTypeName() +" :::: "+ printStr); } class Test<T>{ // List<String>[] pTypeArr > getGenericComponentType > java.util.List<java.lang.String> 为 ParameterizedType // T[] vTypeArr > getGenericComponentType > T 为 TypeVariable public void show(List<String>[] pTypeArr,T[] vTypeArr,List<String> list,String[] strings,int[] ints){} }
WildcardType(通配符类型)
注解:WildcardType 表示一个通配符类型表达式,如 ?、? extends Number 或 ? super Integer。方法
Type[] getUpperBounds();注解:返回表示此类型上限的类型数组。 默认上限是Object。
Type[] getLowerBounds();
注解:返回表示此类型变量的下限的Type对象的数组。 注意,如果没有明确声明下界,下界是null的类型。 在这种情况下,返回零长度数组。
注意:现阶段通配符只接受一个上边界或下边界, 返回数组是为了以后的扩展, 实际上现在返回的数组的大小是1
public class TestType { private List<? extends Number> a; // // a没有下界, 取下界会抛出ArrayIndexOutOfBoundsException private List<? super String> b; public static void main(String[] args) throws Exception { Field fieldA = TestType.class.getDeclaredField("a"); Field fieldB = TestType.class.getDeclaredField("b"); // 先拿到范型类型 Assert.that(fieldA.getGenericType() instanceof ParameterizedType, ""); Assert.that(fieldB.getGenericType() instanceof ParameterizedType, ""); ParameterizedType pTypeA = (ParameterizedType) fieldA.getGenericType(); ParameterizedType pTypeB = (ParameterizedType) fieldB.getGenericType(); // 再从范型里拿到通配符类型 Assert.that(pTypeA.getActualTypeArguments()[0] instanceof WildcardType, ""); Assert.that(pTypeB.getActualTypeArguments()[0] instanceof WildcardType, ""); WildcardType wTypeA = (WildcardType) pTypeA.getActualTypeArguments()[0]; WildcardType wTypeB = (WildcardType) pTypeB.getActualTypeArguments()[0]; // 方法测试 System.out.println(wTypeA.getUpperBounds()[0]); // class java.lang.Number System.out.println(wTypeB.getLowerBounds()[0]); // class java.lang.String // 看看通配符类型到底是什么, 打印结果为: ? extends java.lang.Number System.out.println(wTypeA); } }
总结
之前有误,在此更正:四类Type: | ParameterizedType | TypeVariable | GenericArrayType | WildcardType |
---|---|---|---|---|
示例: | List<String>、List<T> | T、T extends Number | Class<T>[]、Class<?>[] | ?、? extends Number 或 ? super |
注意事项: | getActualTypeArguments获取的Tyep不是TypeVariable就是WildcardType | 只能使用extends进行(多)边界限定, 不能用super. | Class[]、List[]、int[]、String[] 为 Class |
ParameterizedType的getActualTypeArguments获取的Tyep不是TypeVariable就是WildcardType
GenericArrayType的getGenericComponentType不是ParameterizedType就是TypeVariable
包含泛型的变量类型才会是四大Type,不然则为Class
四大Type类型 instanceof Class均为false
然而有些Type instanceof Class为true:
ParameterizedType 的getRawType、getActualTypeArguments、getOwnerType;TypeVariable的getBounds;WildcardType的getUpperBounds、getLowerBounds他们获取的Type中如果不包含泛型,则均为Class类型
综上所属,Java中所有Type对象:
1. Type对象 instanceof Object均为true
2. Type对象包含泛型 instanceof Classs 为false,为四大Type之一
3. Type对象不包含泛型 instanceof Classs 为true,不是四大Type,而是接口Type类型。
class Test<T>{ // List<String> 为 ParameterizedType // T 为 TypeVariable // Class<T>[] 为 GenericArrayType // Class<?>[] 为 GenericArrayType ==> ? 为 WildcardType // List<String>[] pTypeArr > getGenericComponentType > java.util.List<java.lang.String> 为 ParameterizedType // T[] vTypeArr > getGenericComponentType > T 为 TypeVariable // ? 为 WildcardType // Class[]、List[]、int[]、String[]、Class、List、String、int 为 Class // Type要么是四大Type 要么为Class public void show(List[] pTypeArr,T[] vTypeArr,List<String> list,String[] strings,Class[] cls,int[] ints,Set<?> set,T t){} }
参考文章:
详解Java泛型type体系整理
Java类型中ParameterizedType,GenericArrayType,TypeVariabl,WildcardType详解
Java Type详解
Java中的Type详解
相关文章推荐
- Retrofit完全解析(四):Type<应用>
- 关于jsp中<input type="file">获取路径问文件名,获取完全路径问题
- struts.xml文件中<result>的type属性详解
- <iOS>NSXMLParser具体解析xml的应用详解
- ViewPager详解 <一> : 基础知识
- 背包之 01背包、完全背包、多重背包详解 <转载自奋斗哥のblog>
- <Android 基础(二十二)> EditText 无法显示完全以及尝鲜Android N
- 解析<button>跟<input type="button"> 的区别
- javaweb基础学习(二)<request和response详解,以及请求中的乱码问题>
- javaweb基础学习(一)<ServletConfig与ServletContext对象详解>
- 解析<button>和<input type="button"> 的区别
- 完全解析<atlalloc.h>
- [C#基础知识]泛型Dictionary<string,string>的用法详解
- 【Web】<script type="text/template"></script>适合用于定义模板(模板容器),不解析(渲染/执行)
- 【Struts】strust.xml中<result type="">所有类型详解
- <iOS>NSXMLParser具体解析xml的应用详解
- java 从零开始,学习笔记之基础入门<Hibernate_配置详解>(三十六)
- <sytle type="text/css"> 内容解析
- iptables基础<详解> 推荐
- html 标签详解(基础<html> <title>)