黑马程序员--Java基础加强--13.利用反射操作泛型II【TypeVariable】【GenericArrayType】【WildcardType】【Type及其子接口的来历】【个人总结】
2013-08-08 17:16
816 查看
利用反射操作泛型II-----
GenericArrayType接口 TypeVariable接口
WildcardType接口
Type及其及接口的来历
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------1. java.lang.reflect. GenericArrayType接口
1). GenericArrayType类型接口基本知识
(1). GenericArrayType接口的位置GenericArrayType位于java.lang.reflect反射子包中。
(2). GenericArrayType接口类型的含义
表示泛型数组类型。比如:void method(ArrayList<String>[] al){…}
【注意】<>不能出现在数组的初始化中,即new数组之后不能出现<>,否则javac无法通过。但是作为引用变量或者方法的某个参数是完全可以的。
(3). GenericArrayType接口的源码
public interface GenericArrayType extends Type { Type getGenericComponentType(); }
2). GenericArrayType接口的唯一的方法
获取泛型数组中元素的类型[1]. 源码声明:Type getGenericComponentType();
【注意】无论从左向右有几个[]并列,这个方法仅仅脱去最右边的[]之后剩下的内容就作为这个方法的返回值。
[2]. 返回值类型:Type
【分析】为什么返回值类型是Type?
public
static <E> E methodV(
String[] p1,
E[] p2,
ArrayList<E>[] p3,
E[][] p4){}
{1}. 对于String[],通过getComponentType()返回之后,脱去最右边的[]之后,剩余的类型是String。因此对这个参数的返回类型是Class
{2}. 对于E[],通过getComponentType()返回之后,脱去最右边的[]之后,剩余的类型是E。因此对这个参数的返回类型是TypeVariable
{3}. 对于ArrayList<E>[],通过getComponentType()返回之后,脱去最右边的[]之后,剩余的类型是ArrayList<E>。因此对这个参数的返回类型是ParameterizedType
{4}. 对于E[][],通过getComponentType()返回之后,脱去最右边的[]之后,剩余的类型是E[]。因此对这个参数的返回类型是GenericArrayType
因此为统一代码,增强程序的扩展性,使用这些类别的直接公共父类Type作为这个方法的返回值类型。
2. java.lang.reflect. TypeVariable接口
1).TypeVariable类型接口基础知识
(1). TypeVariable接口的位置TypeVariable位于java.lang.reflect反射子包中。
(2). TypeVariable接口类型的含义
表示类型参数或者又叫做类型变量。比如:<E>void method(E e){}中的E就是类型变量
(3). TypeVariable接口的源码
package java.lang.reflect; public interface TypeVariable<D extends GenericDeclaration> extends Type { Type[] getBounds(); DgetGenericDeclaration(); String getName(); }
2). TypeVariable接口的常用方法
(1). 获取类型变量的泛型限定的上边界的类型[1]. 源码声明:Type[] getActualTypeArguments();
【注意】这里面仅仅是上边界。原因就是类型变量在定义的时候只能使用extends进行(多)边界限定。不能使用super,否则编译无法通过。同时extends给出的都是类型变量的上边界。
[2]. 返回值类型:Type元素数组
Type[ ]
【分析1】为什么是返回类型是数组?因为类型变量可以通过&进行多个上边界限定,因此上边界有多个,因此返回值类型是数组类型[
]。
【分析2】为什么数组元素是Type呢?
比如下面的方法:
public
static <E extends Map<String, Date>& Cloneable&Serializable> E methodVI(E e){…}
E的第一个上边界是Map<String, Date>,是ParameterizedType类型
E的第二个上边界是Cloneable,是Class类型
因此,为统一,返回值的数组的元素类型就是Type。
(2). 获取类型变量的定义时候的标示符名称
[1]. 源码声明:String getName();
[2]. 返回值类型:String
3. java.lang.reflect.WildcardType
1). WildcardTyp接口基础知识
(1). WildcardType接口的位置WildcardType位于java.lang.reflect反射子包中。
(2). WildcardType接口类型的含义
表示通配符类型的表达式。
比如 void printColl(ArrayList<? extends Number>al); 中的
? extends Number
(3). WildcardType接口的源码
package java.lang.reflect; public interface WildcardType extends Type { Type[] getUpperBounds(); Type[] getLowerBounds(); // one or many? Up to languagespec; currently only one, but this API // allows for generalization. }
【注意】根据上面API的注释提示:现阶段通配符表达式仅仅接受一个上边界或者下边界,这个和定义类型变量时候可以指定多个上边界是不一样。但是API说了,为了保持扩展性,这里返回值类型写成了数组形式。实际上现在返回的数组的大小就是1
【通配符?指定多个上边界或者下边界编译出错】
2). WildcardType接口的常用方法
(1). 获取通配符表达式对象的泛型限定的上边界的类型[1]. 源码声明:Type[] getUpperBounds();
【注意】上面说了,现阶段返回的Type[ ]中的数组大小就是1个。写成Type[
]是为了语言的升级而进行的扩展。
[2]. 返回值类型:Type元素数组
Type[ ]
【分析】为什么数组元素是Type呢?
比如下面的方法:
{1}. public
static voidprintColl(ArrayList<?extends ArrayList<String>> al){}
通配符表达式是:? extendsArrayList<String>,这样 extends后面是?的上边界,这个上边界是ParameterizedType类型。
{2}. public
static <E> voidprintColl(ArrayList<?extends E> al){}
通配符表达式是:? extends E,这样 extends后面是?的上边界,这个上边界是TypeVariable类型
{3}.public
static <E> voidprintColl(ArrayList<?extends E[]> al){}
通配符表达式是:? extends E[],这样 extends后面是?的上边界,这个上边界是GenericArrayType类型
{4}.public
static <E> voidprintColl(ArrayList<?extends Number> al){}
通配符表达式是:? extends Number,这样 extends后面是?的上边界,这个上边界是Class类型
最终统一成Type作为数组的元素类型。
(2). 获取通配符表达式对象的泛型限定的下边界的类型
[1]. 源码声明:Type[] getLowerBounds();
【注意】上面说了,现阶段返回的Type[ ]中的数组大小就是1个。写成Type[
]是为了语言的升级而进行的扩展。
[2]. 返回值类型:Type元素数组
Type[ ]
4. Type及其子接口的来历
(1). 泛型出现之前的类型没有泛型的时候,只有所谓的原始类型。此时,所有的原始类型都通过字节码文件类Class类进行抽象。Class类的一个具体对象就代表一个指定的原始类型。
(2). 泛型出现之后的类型
泛型出现之后,扩充了数据类型。从只有原始类型扩充了参数化类型、类型变量类型、泛型限定的的参数化类型
(含通配符+通配符限定表达式)、泛型数组类型。
(3). 与泛型有关的类型不能和原始类型统一到Class的原因
[1]. 【产生泛型擦除的原因】
本来新产生的类型+原始类型都应该统一成各自的字节码文件类型对象。但是由于泛型不是最初Java中的成分。如果真的加入了泛型,涉及到JVM指令集的修改,这是非常致命的。
[2]. 【Java中如何引入泛型】
为了使用泛型的优势又不真正引入泛型,Java采用泛型擦除的机制来引入泛型。Java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换的麻烦。但是,一旦编译完成,所有的和泛型有关的类型全部擦除。
[3]. 【Class不能表达与泛型有关的类型】
因此,与泛型有关的参数化类型、类型变量类型、泛型限定的的参数化类型 (含通配符+通配符限定表达式)、泛型数组类型这些类型全部被打回原形,在字节码文件中全部都是泛型被擦除后的原始类型,并不存在和自身类型一致的字节码文件。所以和泛型相关的新扩充进来的类型不能被统一到Class类中。
(4). 与泛型有关的类型在Java中的表示
为了通过反射操作这些类型以迎合实际开发的需要,Java就新增了ParameterizedType,GenericArrayType,TypeVariable
和WildcardType几种类型来代表不能被归一到Class类中的类型但是又和原始类型齐名的类型。
(5). Type的引入:统一 与泛型有关的类型 和 原始类型Class
[1]. 【引入Type的原因】
为了程序的扩展性,最终引入了Type接口作为Class,ParameterizedType,GenericArrayType,TypeVariable和WildcardType这几种类型的总的父接口。这样实现了Type类型参数接受以上五种子类的实参或者返回值类型就是Type类型的参数。
[2]. 【Type接口中没有方法的原因】
从上面看到,Type的出现仅仅起到了通过多态来达到程序扩展性提高的作用,没有其他的作用。因此Type接口的源码中没有任何方法。
【Type源代码】
package java.lang.reflect; public interface Type {}
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------
相关文章推荐
- 黑马程序员--Java基础加强--12.利用反射操作泛型I【与反射+泛型相关的接口类型综述】【Type】【ParameterizedType】【个人总结】
- 黑马程序员--Java基础加强--17.利用反射操作泛型VI【泛型类型变量的语义】【GenericDeclaration接口】【泛型接口TypeVariable】【通过Class反射解析泛型类】
- 黑马程序员--Java基础加强--14.利用反射操作泛型III【解析关于泛型类型的细节信息的获取方法】【Method与泛型相关的方法】【个人总结】
- 黑马程序员--Java基础加强--16.利用反射操作泛型V【通过Constructor反射解析泛型构造方法】【通过Field反射解析泛型成员变量】【个人总结】
- 黑马程序员--Java基础加强--15.利用反射操作泛型IV【通过反射Method解析泛型方法思路】【通过Method对四种Type子接口类型进行解剖】【使用递归对任意复合泛型类型进行彻底解剖】【个人
- 黑马程序员--Java基础加强--07.【反射创建对象 操作字段 调用方法的异同】【个人总结】
- 黑马程序员--Java基础加强--03.代码简化 书写规律II_参数化数据类型【重载】【多态】【泛型】【泛型限定】【个人总结】
- 黑马程序员--Java基础加强--10.【PropertyDescriptor操作JavaBean VS 反射操作Java类】【个人总结】
- 黑马程序员--Java基础加强--06.【泛型通配符限定】【个人总结】
- 黑马程序员--Java基础加强--05.【泛型通配符】【个人总结】
- 黑马程序员--Java基础加强--04.代码简化 书写规律III_数组参数【重载】【数组】【可变参数数组】【泛型可变参数数组】【个人总结】
- 黑马程序员--Java基础加强--02.代码简化 书写规律I_原始数据类型【重载】【多态】【泛型】【泛型限定】【个人总结】
- 黑马程序员--Java基础加强--08.【javac兼容编译原则】【可变参数数组编译】【个人总结】
- 黑马程序员--Java基础加强--11.【MyEclipse使用快捷键提取方法的要点】【个人总结】
- 黑马程序员--Java基础加强--09.【MyEclipse的class文件所在的目录配置】【相对路径解析】【个人总结】
- Java基础---Java---基础加强---内省的简单运用、注解的定义与反射调用、 自定义注解及其应用、泛型及泛型的高级应用、泛型集合的综合
- 黑马程序员:Java基础总结----子接口 List<E>及其实现类
- 黑马程序员-->Java基础加强-->泛型(Generic)
- 黑马程序员:Java基础总结----子接口 set<E>及其实现类
- 黑马程序员_java基础加强_静态导入_反射_枚举_注解_内省_泛型_代理