作者 | 朱钢,责编 | 郭芮

头图 | CSDN 下载自东方IC

出品 | CSDN(ID:CSDNnews)

开发人员会经常用到泛型,并且大部分开发人员都会很好的使用泛型。泛型需要底层运行时的支持,泛型类中类型参数变成了元数据,在运行时需要时会利用她们来构造恰当的类,因此泛型支持继承、多态和封装。简单地说了一下泛型深层的知识,下面我们来看看泛型的内部机制到底是什么。

CIL 表示泛型

泛型类在经过编译后其实和普通类编译后的结果并没什么太大的出入,结果都是 CIL 和元数据,唯一的区别是 CIL 会用特殊的标记来表示该编译结果为泛型类的编译结果,我们通过一个例子来看一下。

public class Demo<T> where T:IComparable{//more codeT[] item;//more code}

上述代码中定义了一个 Demo 泛型类,它包含一个类型参数。经过变异后最终生成的参数化 CIL 代码如下:

.class private auto ansi beforefieldinit Demo'1 <[mscorlib]System.IComparable)T> extends [mscorlib]System.Object{//more CIL code.field private !0[ ] items//more CIL code}

在上述参数化 CIL 代码中我们看到在 Demo 后面出现了一个 '1 ,它叫做元数也就是参数数量,表示声明泛型类时要求的类型实参的数量,上面的这个例子因为只一个类型参数因此他需要的类型实参的数量就是 1 个,如果是 Demo<TKey,TValue,Tother> 这样的泛型类的话,生成的参数化 CIL 代码中的类型实参数量就是 3,表示为 '3 。在参数化 CIL 代码中显示了施加在类上的约束,既 [mscorlib]System.IComparable 。同时 CIL 代码修改了定义的 T 类型数组声明,使用 ! 包含一个类型参数。除了上说所说的三点之外,生成的其他 CIL 代码和普通类生成的代码没什么区别。

值类型泛型实例化

当用值类型作为类型参数构造泛型类型时为了创建具体化的泛型类型,运行时会在 CIL 合适的位置放上指定的类型参数。

当我们首次调用上一小节中定义的泛型类 Demo 并将 int 作为类型实参传递给 Demo 时,运行时会生成 Demo 的具体化版本,并使用 int 替换类型参数。这样每次使用 Demo<int> 的时候运行时都会重用已经生成的具体化类 Demo<int> 。这里需要注意的是生成的具体化类只针对类型实参是 int 的情况下,如果这时又定义了一个以 float 为类型实参的 Demo 时,运行时将会再生成泛型类型的另一个版本。

使用值类型泛型实例能避免代码的转换和装箱操作进而提高性能,但是在使用过程中也需要根据具体代码、具体情况和具体项目来判断值类型泛型是否该使用该怎么使用。

Tip:运行时会为每个新的只类型参数创建一个具体的泛型类型。

引用类型泛型实例化

泛型实例在使用引用类型作为类型实参的时候和值类型有点不同。在构造泛型类型时运行时会在 CIL 代码中使用 object 引用替换类型参数来创建具体化泛型类型,当每次使用引用类型参数实例化构造好的类型时,运行时都会重用已经生成好的版本,这里需要注意的是如果提供的引用类型和构造泛型类型时的引用类型不同,它依然会使用已经生成好的那个版本。下面看一个例子:

Demo<User> userDemo;Demo<Student> studentDemo;

首先当代码运行到第一行时,运行时会生成 Demo 的具体化版本,CIL 不会存储 User 作为制定的数据类型,而是存储 object 引用。然后代码运行到第二行时,虽然 Student 和 User 的引用不同但是 CIL 不会为 Student 创建一个新的具体化版本,而是实例化前面给予 object 引用的 Demo 的实例。当然,为了确保类型安全, CIL 会分配给 Order 类型一个内存区域来替换类型参数的每个 object 引用导致向这个内存区域。使用引用类型泛型的好处是编译器将它创建的具体化类压缩至 1 个,因此大大减少了代码量,提高了代码的性能。

这里需要注意,引用类型类型参数在发生变化时运行时使用相同内部泛型类型定义,但是如果出现如下的情况,那么就不会适用相同的内部泛型类型定义。

Demo<int,User> userDemo;Demo<long,User> userLongDemo;Demo<Guid,User> userGuidDemo;

在上述代码中类型参数包含值类型,这时就不会使用相同的内部泛型类型定义,而是为每个 Demo 创建不同的内部类型定义。

小结

这篇文章虽然简短,但是充分讲解了泛型机制的内部原理以及相关注意事项。.NET 中的泛型可以说是最好的,在 Java 中使用泛型完全是在编译器中实现的而不是在 JVM 中实现的,虽然这样可以预防使用泛型而分发新的 JVM ,但是由于它不区分值类型和引用类型,所以执行效率底以及影响到反射部分功能的使用。

作者:朱钢,.NET高级开发工程师,7年一线开发经验,参与过电子政务系统和AI客服系统的开发,以及互联网招聘网站的架构设计,目前就职于北京恒创融慧科技发展有限公司。

声明:本文系作者原创投稿,未经允许请勿转载。

【END】

更多精彩推荐

百年 IBM 终于 All In 人工智能和混合云!

☞微软、苹果、谷歌、三星……这些区块链中的科技巨头原来已经做了这么多事!

☞斩获GitHub 2000+ Star,阿里云开源的 Alink 机器学习平台如何跑赢双11数据“博弈”?| AI 技术生态论

☞微软为一人收购一公司?破解索尼程序、写黑客小说,看他彪悍的程序人生!

机器学习项目模板:ML项目的6个基本步骤

☞IBM、微软、苹果、谷歌、三星……这些区块链中的科技巨头原来已经做了这么多事!

资深程序员总结:分析Linux进程的6个方法,我全都告诉你

今日福利:评论区留言入选,可获得价值299元的「2020 AI开发者万人大会」在线直播门票一张。  快来动动手指,写下你想说的话吧。

点击阅读原文,精彩继续!

你点的每个“在看”,我都认真当成了喜欢

程序员常用的泛型机制究竟怎么玩?相关推荐

  1. 最全程序员常用术语,科技互联网翻译必备

    最全程序员常用术语,科技互联网翻译必备 (整理不易,给个赞叭 蟹蟹) A abstract 抽象的 abstract base class (ABC)抽象基类 abstract class 抽象类 a ...

  2. 600个程序员常用的单词和词汇

    600个程序员常用的单词和词汇 来自:网络 一小时轻松掌握程序员单词 1小时搞定程序员单词 集结了600个程序员常用的单词和词汇,让你写代码变量命名 so easy!!! 还等什么!GOGOGO! a ...

  3. java excel 插件开发工具_程序员常用的15 种开发者工具推荐

    程序员常用的15 种开发者工具推荐:Java 线上诊断工具 Arthas.IDE 插件 Cloud Toolkit.混沌实验注入工具 ChaosBlade.Java 代码规约扫描插件.应用实时监控工具 ...

  4. 阿里程序员常用的 15 个高效工具,大部分已开源!

    阿里程序员常用的 15 个高效工具,大部分已开源! 阿里将自身在各类业务场景下的技术积淀,通过开源.云上实现或工具等形式对外开放,本文将精选了一些阿里巴巴的开发者工具,希望能帮助开发者们提高开发效率. ...

  5. 这份程序员常用技术栈和工具清单,刷爆朋友圈……

    基于Java的Web应用开发技术已成为目前Web开发的主流技术,作为一名Java程序员,到底要掌握什么技术才能完成一个JavaWeb项目呢? 小编和一位十年经历程序员要来这份Java程序员常用技术栈, ...

  6. 收录Java程序员常用英语

    Java程序员常用英语 基础----进阶 A. array数组accessible 可存取的  area面积audio 音频   addition  加法  action 行动  arithmetic ...

  7. Java程序员常用英语

    干程序员这行实在是离不开英语,干程序员是一项很辛苦的工作,要成为一个高水平的程序员尤为艰难.这是因为计算机软件技术更新的速度越来越快,而这些技术大多来源于英语国家,我们在引进这些技术时往往受到语言障碍 ...

  8. Java程序员常用英语词汇

    干程序员这行实在是离不开英语,干程序员是一项很辛苦的工作,要成为一个高水平的程序员尤为艰难.这是因为计算机软件技术更新的速度越来越快,而这些技术大多来源于英语国家,我们在引进这些技术时往往受到语言障碍 ...

  9. 程序员常用的六大技术博客类

    程序员越来越多,相对应的博客,论坛,社区也乱花渐欲迷人眼,呈现出一个逐渐增长的趋势,以下写的都是一些自己常用的平台,这些平台在百度上面的权重还是很高的,偶尔搜索关键字还能跳出自己写过的博客,于是稍微的 ...

最新文章

  1. 2017海克斯康拉斯维加斯美国大会 精彩即将开始
  2. IDEA+Maven运行调试MapReduce程序
  3. 开源,免费和跨平台 - MVP ComCamp 2015 KEYNOTE
  4. MySQL高级 - 案例 - 系统性能优化 - 数据源配置
  5. PyCharm-professional-2018.2.2 - 破解
  6. Confluence 6 为空白空间编辑默认主页
  7. IBM软件OEM概览
  8. c语言作业请输入一个运算符,C语言书面作业1(有答案版)..doc
  9. java joda_java-Jodatime的开始时间和结束时间
  10. extjs 中登录保存用户名
  11. C语言十进制转二进制
  12. linux中文件大小设置函数,truncate函数和ftruncate修改文件大小-linux
  13. java 蓝桥杯算法训练 连续正整数的和(题解)
  14. Java查找一个字符串中所有匹配某正则的子串
  15. 【笔试/面试】排列组合与概率计算(三)
  16. shell编程规范与变量
  17. Publish Junit test result report
  18. Win7 安装 -- SHSUCDX can’t install 问题解决
  19. win7电脑蓝屏没有修复计算机,Win7旗舰版系统电脑老是出现蓝屏的修复教程
  20. DTI数据处理: from scanner to statistics

热门文章

  1. 基于ssh的多节点之间互信通信的实现
  2. 跨域-(jsonp cors)
  3. 漫谈并发编程(三):共享受限资源
  4. git push的时候报Unable to find remote helper for 'https'的错误
  5. AsciidocFX相关
  6. 《计算机网络》学习笔记 ·002【物理层】
  7. windows下yolov4-deepsort项目tensorflowGPU版本配置+项目实战
  8. 汽车燃料效率分析实例
  9. python编辑器编程猫_编程猫Python编辑器 Mac版0.4.0 下载 - 51下载网
  10. Linux多进程编程(2)