作者
夏梓耀
杏仁后端工程师,励志成为计算机艺术家
总结为什么文章的一开头会是总结?因为我怕你看不到最后(¬_¬),本文不止是内容上过于偏重理论,信息量还非常大,但我不喜欢分篇,因为我觉得它是完整的。
虽然写了一万多字(写了半个月_(:з」∠)_),但是还是有很多东西不是讲的很清楚,一是删减了一些理论背景(可能需要你额外去学习一下),精简后只保留了核心部分;二是本人水平的问题(逃
本文描述的是类型系统,一个只存在于编译阶段描述类型检查的形式系统(连个具体的程序都不是),是被广大程序员忽略的存在;并且还常常听到这样的言论:不要做编译器的奴隶(我经常在一些动态类型语言的广告里看到这样的话),是的,不要做编译器的奴隶,并不是应该抛掉编译器(的类型检查器),而是应该了解编译器,并且做编译器的主人,这才是正确的。
对程序员来说,编译器(的类型检查器)是一种财富,是你的武器,我们应该掌握语言的类型系统,并且让它更好的为我们服务,保证程序的安全性(正确性),在编译阶段就将犯错的可能性扼杀掉(即:将BUG杀死在摇篮中)
良好的类型定义也是一份良好的文档,会让我们的接口语义更加清晰,我们应该花时间思考类型定义,并且尽可能细化类型的定义。
本文是我学习的类型系统相关理论知识和Java类型系统的一篇总结,涉及到Java是希望将理论知识与实践结合(从而不无聊)。
Java类型系统众所周知,Java在Java.0引入了泛型(Generics)aka参数化多态(parametricpolymorphism),进一步的提高了类型安全性(typesafe),对开发者来说最大的变化应该是:从一个集合里取出一个元素终于不需要强制类型转换(cast)了。
参数化多态(ParametricPolymorphism)为什么要引入参数化多态?因为它提高了语言的抽象能力,参数化多态意味着我们仅需写一个参数化的方法,比如:
P,QQf(FunctionP,Qf,Pp){returnf(p);}
从而就有了:
Integerf(FunctionString,Integerf,Stringp){...}Booleanf(FunctionString,Booleanf,Stringp){...}Stringf(FunctionInteger,Stringf,Integerp){...}...
无数个方法,大大减少了重复性。
稍微理论一点的说法就是:具体类型,比如ListInteger、ListString都被一个类型参数T给索引了,当T为Integer时,ListT为ListInteger,Integer就是T的具体化/实例(instantiate)。
子类型化(Subtyping)除了参数化多态,Java作为一门面向对象的语言,本身就有面向对象类型系统的核心特征:子类型多态(subtypepolymorphism),也就是我们常说的"继承、封装、多态"的"多态"。这个大家都比较熟了(平常用的最多的特性),不过Java在引入参数化多态的时候,其实是有对很多提案进行比较和权衡的,因为要做的不仅是单纯的引入参数化多态,还要考虑与现有的子类型结合起来。
边界/囿[yòu]量词(BoundedQuantification)首先是对参数化多态的扩展,支持给泛型变量添加边界,即:TextendsX等,这样可以表示更加精确的类型约束,而不仅仅是forall;不仅如此,Java还支持F-bounded,即类型变量可以出现在自己的上边界中:TextendsFT,这有什么用呢?举个熟悉的例子:
interfaceComparableT{publicint北京治疗白癜风费用多少钱白癜风该如何治疗