(1). 和反射+泛型有关的接口类型
java.lang.reflect.Type:java语言中所有类型的公共父接口
java.lang.reflect.ParameterizedType
java.lang.reflect.GenericArrayType
java.lang.reflect.WildcardType

  1. Type直接子接口
    ParameterizedType,GenericArrayType,TypeVariable和WildcardType四种类型的接口
    ParameterizedType: 表示一种参数化的类型,比如Collection

GenericArrayType: 表示一种元素类型参数化类型或者类型变量数组类型
TypeVariable: 是各种类型变量公共父接口
WildcardType: 代表一种通配符类型表达式,比如?, ? extends Number, ? super Integer【wildcard是一个单词:就是“通配符”】

  1. Type直接实现子类 :Class类
    ****3. java.lang.reflect.Type接口
    Type所有类型指代的有:原始类型 (raw types)【对应Class】参数化类型 (parameterizedtypes)【对应ParameterizedType】, 数组类型 (array types)【对应GenericArrayType】,类型变量 (type variables)【对应TypeVariable】,基本数据类型(primitivetypes)【仍然对应Class】
    ****4. java.lang.reflect.ParameterizedType接口
    ParameterizedType接口类型的含义
    表示参数化类型。比如:Map这种参数化类型

获取参数化类型<>中的实际类型
源码声明:Type[] getActualTypeArguments();
【注意】无论<>中有几层<>嵌套,这个方法仅仅脱去最外层的****<>之后剩下的内容就作为这个方法的返回值
public static E methodIV(

ArrayList> al1,

ArrayList al2,

ArrayList al3,

ArrayListextends Number> al4,
ArrayList al5){} 那么他的每一参数总体上看都是参数化类型的。
{1}. 对于ArrayList>,通过getActualTypeArguments()返回之后,脱去最外层的<>之后,剩余的类型是ArrayList
因此对这个参数的返回类型是ParameterizedType

{2}. 对于ArrayList,通过getActualTypeArguments()返回之后,脱去最外层的<>之后,剩余的类型是E。因此对这个参数的返回类型是TypeVariable

{3}. 对于ArrayList,通过getActualTypeArguments()返回之后,脱去最外层的<>之后,剩余的类型是String。因此对这个参数的返回类型是Class

{4}. 对于ArrayListextends Number>,通过getActualTypeArguments()返回之后,脱去最外层的<>之后,剩余的类型是? ExtendsNumber。因此对这个参数的返回类型是WildcardType
{5}. 对于ArrayList,通过getActualTypeArguments()返回之后,脱去最外层的<>之后,剩余的类型是E[]。因此对这个参数的返回类型是GenericArrayType

所以,可能获得各种各样类型的实际参数,所以为了统一,采用直接父类数组Type[]进行接收。

  1. java.lang.reflect. GenericArrayType接口
    GenericArrayType接口类型的含义
    表示泛型数组类型。比如:void method(ArrayList[] al){…}****

【注意】<>不能出现在数组的初始化中,即new数组之后不能出现<>,否则javac无法通过。但是作为引用变量或者方法的某个参数完全可以的
获取泛型数组中元素的类型
源码声明:Type getGenericComponentType();
【注意】无论从左向右有几个[]并列,这个方法仅仅脱去最右边的****[]之后剩下的内容就作为这个方法的返回值
为什么返回值类型Type
public static E methodV(

String[] p1,
E[] p2,
ArrayList[] p3,

E[][] p4){}
{1}. 对于String[],通过getComponentType()返回之后,脱去最右边的[]之后,剩余的类型是String。因此对这个参数的返回类型是Class
{2}. 对于E[],通过getComponentType()返回之后,脱去最右边的[]之后,剩余的类型是E。因此对这个参数的返回类型是TypeVariable
{3}. 对于ArrayList[],通过getComponentType()返回之后,脱去最右边的[]之后,剩余的类型是ArrayList
因此对这个参数的返回类型是ParameterizedType

{4}. 对于E[][],通过getComponentType()返回之后,脱去最右边的[]之后,剩余的类型是E[]。因此对这个参数的返回类型是GenericArrayType

  1. java.lang.reflect. GenericArrayType接口
    TypeVariable接口类型的含义
    表示类型参数或者又叫做类型变量。比如:void method(E e){}中的E就是类型变量

获取类型变量的泛型限定的上边界的类型
源码声明:Type[] getActualTypeArguments();
【注意】这里面仅仅是上边界。原因就是类型变量定义的时候只能使用extends进行(多)边界限定不能使用super,否则编译无法通过。同时extends给出的都是类型变量上边界
为什么是返回类型是数组?因为类型变量可以通过&进行多个上边界限定,因此上边界有多个,因此返回值类型是数组类型[ ]
例如下面的方法:
public static extends Map& Cloneable&Serializable> E methodVI(E e){…}

E的第一个上边界是Map,是ParameterizedType类型

E的第二个上边界是Cloneable,是Class类型
因此,为统一,返回值的数组的元素类型就是Type

  1. java.lang.reflect.WildcardType接口
    WildcardType接口类型的含义
    表示通配符类型的表达式。
    比如** void printColl(ArrayListal); 中的 ? extends Number
    注意】根据上面API的注释提示:现阶段通配符表达式仅仅接受一个上边界或者下边界,这个和定义类型变量时候可以指定多个上边界是不一样。但是API说了,为了保持扩展性,这里返回值类型写成了数组形式。实际上现在返回的数组的大小就是1**
    获取通配符表达式对象的泛型限定的上边界的类型
    源码声明:Type[] getUpperBounds();
    【注意】上面说了,现阶段返回的****Type[ ]中的数组大小就是1个。写成Type[ ]是为了语言的升级而进行的扩展。
    例如下面的方法:
    {1}.** public static void**printColl(ArrayListextends ArrayList> al){}

通配符表达式是:? extendsArrayList,这样 extends后面是?的上边界,这个上边界是ParameterizedType类型。

{2}. public static voidprintColl(ArrayListextends E> al){}

通配符表达式是:? extends E,这样 extends后面是?的上边界,这个上边界是TypeVariable类型
{3}.public static voidprintColl(ArrayListextends E[]> al){}

通配符表达式是:? extends E[],这样 extends后面是?的上边界,这个上边界是GenericArrayType类型
{4}.public static voidprintColl(ArrayListextends Number> al){}

通配符表达式是:? extends Number,这样 extends后面是?的上边界,这个上边界是Class类型
最终统一成Type作为数组的元素类型。

  1. Type及其子接口的来历
    一. 泛型出现之前的类型
    没有泛型的时候,只有所谓的原始类型。此时,所有的原始类型都通过字节码文件类Class类进行抽象Class类的一个具体对象就代表一个指定的原始类型
    二. 泛型出现之后的类型
    泛型出现之后,扩充了数据类型。从只有原始类型扩充了参数化类型类型变量类型泛型限定的的参数化类型 (含通配符+通配符限定表达式)泛型数组类型
    三. 与泛型有关的类型不能和原始类型统一到Class的原因
    [1]. 【产生泛型擦除的原因
    本来新产生的类型+原始类型都应该统一成各自的字节码文件类型对象。但是由于泛型不是最初Java中的成分。如果真的加入了泛型,涉及到JVM指令集的修改,这是非常致命的。
    [2]. 【Java中如何引入泛型
    为了使用泛型的优势又不真正引入泛型,Java采用泛型擦除的机制来引入泛型。Java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换的麻烦。但是,一旦编译完成,所有的和泛型有关的类型全部擦除
    [3]. 【Class不能表达与泛型有关的类型
    因此,与泛型有关参数化类型类型变量类型泛型限定的的参数化类型 (含通配符+通配符限定表达式)泛型数组类型这些类型全部被打回原形,在字节码文件中全部都是泛型被擦除后的原始类型,并不存在和自身类型一致的字节码文件。所以和泛型相关的新扩充进来的类型不能被统一到Class类中。
    (4). 与泛型有关的类型在Java中的表示
    为了通过反射操作这些类型以迎合实际开发的需要,Java就新增了ParameterizedTypeGenericArrayTypeTypeVariableWildcardType几种类型来代表不能被归一到Class类中的类型但是又和原始类型齐名的类型
    (5). Type的引入:统一与泛型有关的类型和原始类型Class
    引入Type的原因
    为了程序的扩展性,最终引入了Type接口作为ClassParameterizedTypeGenericArrayTypeTypeVariableWildcardType这几种类型的总的父接口。这样实现了Type类型参数接受以上五种子类的实参或者返回值类型就是Type类型的参数。
    Type接口中没有方法的原因
    从上面看到,Type的出现仅仅起到了通过多态来达到程序扩展性提高的作用,没有其他的作用。因此Type接口的源码中没有任何方法。

作者:Android技术研究
链接:https://www.jianshu.com/p/d1a27fe7dfd6
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

Java类型中ParameterizedType,GenericArrayType,TypeVariabl,WildcardType详解的更多相关文章

  1. [ 转载 ] Java开发中的23种设计模式详解(转)

    Java开发中的23种设计模式详解(转)   设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类 ...

  2. Java开发中的23种设计模式详解

    [放弃了原文访问者模式的Demo,自己写了一个新使用场景的Demo,加上了自己的理解] [源码地址:https://github.com/leon66666/DesignPattern] 一.设计模式 ...

  3. Java开发中的23种设计模式详解(转)

    设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

  4. java开发中的23中设计模式详解--大话设计模式

    设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

  5. 0. Java开发中的23种设计模式详解(转)

    设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

  6. (转)Java开发中的23种设计模式详解

    原文出自:http://blog.csdn.net/zhangerqing 一.设计模式的分类 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型 ...

  7. 【java】java开发中的23种设计模式详解

    设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

  8. Java开发中的23种设计模式详解(转载)

    前学习过一段时间的设计模式,总是感觉学习的不够清楚.现在再重新复习一下,原文地址:https://blog.csdn.net/doymm2008/article/details/13288067 一. ...

  9. 面试题:Java开发中的23种设计模式详解(转)

    设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

随机推荐

  1. 突变注释工具SnpEff,Annovar,VEP,oncotator比较分析--转载

    https://www.jianshu.com/p/6284f57664b9 目前对于variant进行注释的软件主要有4个: Annovar, SnpEff, VEP(variant Effect ...

  2. 转 Failed to run the WC DB work queue associated with 错误的解决

    svn 异常终止导致的缓存工作队列问题 解决方法:清空svn的队列 1.下载sqlite3.exe 2.找到你项目的.svn文件,查看是否存在wc.db 3.将sqlite3.exe放到.svn的同级 ...

  3. 四: scrapy爬虫框架

    5.爬虫系列之scrapy框架   一 scrapy框架简介 1 介绍 (1) 什么是Scrapy? Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架,非常出名,非常强悍.所谓的框架 ...

  4. L1-047. 装睡

    水题直接上代码: #include<iostream> #include<algorithm> using namespace std; int main() { int n; ...

  5. django序列化 serializers

    Django的序列化工具让你可以将Django的模型‘翻译’成其它格式的数据.通常情况下,这种其它格式的数据是基于文本的,并且用于数据交换\传输过程. 一.序列化数据 Django为我们提供了一个强大 ...

  6. MySQL学习(五)

    查询数据的学习与练习 建立一个表 CREATE TABLE goods ( `goos_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, `cat_ ...

  7. Qt访问注册表并调用子进程

    在实际应用中需要在一个进程启动另外一个进程,可以将子进程的路径写入注册表中,然后主进程读取注册表中子进程路径,启动子进程,并以命令行参数的形式传入参数,启动子进程.具体实现方式如下 (1)      ...

  8. KMP算法(next数组方法)

    KMP算法之前需要说一点串的问题: 串: 字符串:ASCII码为基本数据形成的一堆线性结构. 串是一个线性结构:它的存储形式: typedef struct STRING { CHARACTER *h ...

  9. Codeforces 937D - Sleepy Game

    937D - Sleepy Game 思路: dfs. vis[u][0]==1表示u这个点能从s点偶数路径到达 vis[u][1]==1表示u这个点能从s点奇数路径到达 这个样就能保证dfs时每个点 ...

  10. ios手机域名https协议注意事项

    加载网页版链接框架不能用http 1.下载到本地 2.转换为cdn https