1。新国王登基后的第一天早上,神采奕奕的爪哇第五代国王坐在宝座上,看着下方恭敬的大臣们,心情大好。他已经下定决心改革官僚机构,摆脱劣势,让爪哇帝国更上一层楼。国王的第一道命令,就是要求所有大臣展开一场轰轰烈烈的自查运动,检查自己负责的领域,听取帝国臣民的声音。半个月后,每位大臣至少要上报三项合理建议。下面的大臣们认为这一定是三分钟热病,过一会国王就会忘记了。虽是这么想,但还是说道:“陛下英明,真是创举,定能使我爪哇帝国万古长青。”没想到半个月后,国王真的又开始检查作业了:“IO部长,那里的情况怎么样了?”老奸巨猾的IO大臣虽然愣了一下,但随即回过神来:“陛下,自从我们爪哇帝国建立以来,制度近乎完善,国家兴盛,都是靠我们先祖的努力。繁荣昌盛,人民安康。”都赞,我这里真的没什么可改进的。”其他大臣也附和道:“IO大臣说的很对,我这里也查不到。”国王看着这些不务正业的官僚,恨得咬牙切齿:“哼!你们没有,我这里有。来,让C++帝国的使者入宫!”他凝视着走进去,在大殿中央向国王行了一礼。大王说:“这位是C++大王的使者,他带来了一个我们帝国没有的新玩意儿。泛型先生,一路辛苦了,请介绍一下C++王国的泛型吧。””看来国王早就和这家伙勾搭上了,等着给我们好看,小心点,IO大臣警惕。那个叫泛型先生的家伙说:“Java语言以严谨着称,但是在设计的时候并没有考虑到泛型这个重要的概念。真不应该。举个例子?丝路部长 问道。Generics先生展示了一段代码:collectionframework的部长看到这小子想自杀,还不错。”他接过话头道:“有什么问题?男孩说,“我加一个String和Integer好像没问题,但是用List的人就麻烦了,他肯定知道第一个元素是string类型,第二个是Integer类型,必须强制转换,否则会出错。”“这不是很正常吗?”CollectionFramework部长问:“写程序的编码员必须记住每个元素的类型。而且我的List可以容纳任何类型的元素,多么灵活!”Pan类型使者说:“这样做会增加使用者的责任,编译器也无能为力,运行时会抛出ClassCast异常。”“那你说说,编译器能帮上什么忙?”来这里的目的是,在我的家乡C++帝国,我们可以定义一个模板类,例如:""这里定义了一个模板类List,通过它可以实例化任何你想要的类型,例如List,List,List……上面的代码实例化了一个List,所以只能往里面添加整数,如果添加字符串等其他类型的值,编译器会可以检查出来直接报错。我们的C++帝国称这种能力为泛型(Generics)”集合框架大臣笑道:“哈哈,这么奇葩的语法,怪不得你们的C++越来越....”Java王威严的目光,将后半句咽了回去,“亲爱的亲爱的,我猜你已经看到了,这个‘泛型’可以在编译时检查错误,用List的人不用强制转换,还是很有用的。我们也应该在Java中添加类似的功能。”“怎么加呢?”集合框架大臣问道。“很简单,按照C++的语法就行了。将来被取代。国王让卢公公展开一张写满代码的纸:“看这个代码,看有没有T,你可以把它当成一个占位符,以后可以传入任何类型,比如Integer,String等“等等”集合框架大臣看到king连代码都写好了,觉得king真的很勤奋,看来下定决心要做这件事3.GenericImplementation的IO大臣道:“陛下英明,我愚钝,还有一件事不知。这个所谓的泛型是怎么实现的呢?”C++泛型使者说:“在我们的C++帝国里,每去实例化一个泛型/模板类,都会生成一个新的类,比如模板类是List,而那么你分别用int,double,string,Employee来实例化,那么编译的时候,我们会生成四个新的类,比如List_int和List_double,List_string,List_Employee。”集合框架部长说:“啊?!这样会产生很多新的类,系统会不会膨胀到爆炸。”大王说:“不用担心,我已经给C++的泛型使者深入讨论过,我们不用膨胀的方法,“擦除法?”众大臣面面相觑。作为一个ArrayList。”“那我传入的String,Integer等会消失吗?”集合框架部长吓得脸色苍白。“不,我会把它们变成Objects。比如ArrayList其实就是擦写成了原来的ArrayList:get(0);现在type被擦除,全部变成Objects,怎么处理?”Java之王说:“很简单,编译的时候手脚并用,加个自动转换:Integeri=(Integer)list1.get(0);”“陛下真是高瞻远瞩,本王给您拜一拜。”IO部长立刻受宠若惊。4.泛型方法集合框架大臣说:“陛下,您刚才说的是泛型类,有些静态方法怎么办?”“很简单,将移到方法中!”王令无疑,集合框架大臣看了一会,自言自语道:“这个静态函数是计算最大值,也就是需要比较List中元素的大小。如果主体传入的T没有实现Comparable接口,无法比较大小!”线程部长和IO部长点头同意。王国觉得这些大臣也不是没用,还是有些想法的,转头看向C++使者:“这是一道难题,Genericmessenger,你怎么看?”传入的类型T必须是Comparable的子类,否则编译器会报错,我建议使用extends关键字。”C++的泛型使者看来很有经验。五百两!”IO大臣提议:“陛下,我建议泛型使者在京城多住几天,帮助我们实现Java泛型。”国王说:“准奏,这是一件大事。希望各位亲爱的朋友们一起努力。做完了,给你重赏。”(老刘注:Java泛型除了extends,还支持super,其实为了更灵活,上面的Comparable应该写成Comparable,在此不再赘述。)5.经过几个月的泛型和继承准备,Java泛型正式上线,开始被臣民使用起来。正如君臣所料,泛型大大减少了引发的异常通过runtime的那些transitions,简化了代码,受到了大家的一致欢迎。king专门设置了一个genericminister的位置,暂时让collectionframework兼任部长,没办法,collectionframework的变化是泛型的一个亮点。几天后,Generics部长和CollectionFramework部长发表了一篇奏折,上面有一张图片和一些代码:王者惊奇,这是怎么回事,打印函数不是可以接受ArrayList的参数吗<水果>?为什么传递ArrayList是错误的?我们Java帝国的多态是不是不行了?他召来通才大臣询问。通用大臣说:“陛下,虽然这个Apple是Fruit的子类,但是ArrayList不是ArrayList的子类,实际上它们之间没有关系,不能进行转换操作,所以调用print的时候报错,“为什么ArrayList不能转换成ArrayList?”销毁了“哦,原来如此”国王心想,泛臣还是不错的。“那刚才的问题怎么办?””我和大臣商量过,我们打算引入通配符的方法来解决,函数的入参改成如下:“”也就是说,只要传入的参数是Fruit或者子类就可以了水果的,没问题吧?”国王看到了钥匙。“嗯,虽然看起来有点不爽,但还是这么实施吧!”【本文为专栏作家“刘鑫”原创文章,如需稿件,请通过作者微信获取授权公众号coding】点此查看作者更多好文