




已阅读5页,还剩28页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
课件制作人 XXX Java实用教程 第5章泛型 Jdk1 5中的新特性 泛型 在Java中能使用到泛型的多是容器类 如各种listmapset 因为Java是单根继承 所以容器里边可以放的内容是任何Object 所以从意义上讲原本的设计才是泛型 但用过Java的人是否感觉每次转型很麻烦呢 而且会有些错误 比如一个容器内放入了异质对象 强制转型的时候会出现cast异常 而这中错误在编译器是无从发现的 所以jdk1 5中提供了泛型 这个泛型其实是向c 靠拢了 我们先看几个实例再细说原理 1 引言 ListmyIntList newLinkedList 1myIntList add newInteger 0 2Integerx Integer myIntList iterator next 3 第3行的类型转换有些烦人 通常情况下 程序员知道一个特定的list里边放的是什么类型的数据 但是 这个类型转换是必须的 essential 编译器只能保证iterator返回的是Object类型 为了保证对Integer类型变量赋值的类型安全 必须进行类型转换 当然 这个类型转换不仅仅带来了混乱 它还可能产生一个运行时错误 runtimeerror 因为程序员可能会犯错 程序员如何才能明确表示他们的意图 把一个list中的内容限制为一个特定的数据类型呢 这是generics背后的核心思想 这是上面程序片断的一个泛型版本 ListmyIntList newLinkedList 1myIntList add newInteger 0 2Integerx myIntList iterator next 3 注意变量myIntList的类型声明 它指定这不是一个任意的List 而是一个Integer的List 写作 List 我们说List是一个带一个类型参数的泛型接口 agenericinterfacethattakesatypeparameter 本例中 类型参数是Integer 我们在创建这个List对象的时候也指定了一个类型参数 另一个需要注意的是第3行没了类型转换 用第1行的类型参数取代了第3行的类型转换 然而 这里还有个很大的不同 编译器现在能够在编译时检查程序的正确性 当我们说myIntList被声明为List类型 这告诉我们无论何时何地使用myIntList变量 编译器保证其中的元素的正确的类型 与之相反 一个类型转换说明程序员认为在那个代码点上它应该是那种类型 实际结果是 这可以增加可读性和稳定性 robustness 尤其在大型的程序中 2 定义简单的泛型 下面是从java util包中的List接口和Iterator接口的定义中摘录的片断 publicinterfaceList voidadd Ex Iteratoriterator publicinterfaceIterator Enext booleanhasNext 类型参数就跟在方法或构造函数中普通的参数一样 就像一个方法有形式参数 formalvalueparameters 来描述它操作的参数的种类一样 一个泛型声明也有形式类型参数 formaltypeparameters 当一个方法被调用 实参 actualarguments 替换形参 方法体被执行 当一个泛型声明被调用 实际类型参数 actualtypearguments 取代形式类型参数 一个命名的习惯 我们推荐你用简练的名字作为形式类型参数的名字 如果可能 单个字符 最好避免小写字母 这使它和其他的普通的形式参数很容易被区分开来 许多容器类型使用E作为其中元素的类型 就像上面举的例子 在后面的例子中还会有一些其他的命名习惯 3 泛型和子类继承 测试一下我们对泛型的理解 下面的代码片断合法么 Listls newArrayList 1Listlo ls 2第1行当然合法 但是这个问题的不好理解之处在于第2行 这产生一个问题 一个String的List是一个Object的List么 大多数人的直觉是回答 当然 在看下面的几行 lo add newObject 3Strings ls get 0 4 试图把Object赋值给String这里 我们使用lo指向ls 我们通过lo来访问ls 一个String的list 我们可以插入任意对象进去 结果是ls中保存的不再是String 当我们试图从中取出元素的时候 会得到意外的结果 java编译器当然会阻止这种情况的发生 第2行会导致一个编译错误 总之 如果Foo是Bar的一个子类型 子类或者子接口 而G是某种泛型声明 那么G是G的子类型并不成立 3 泛型和子类继承 4 通配符 Wildcards 考虑写一个例程来打印一个集合 Collection 中的所有元素 下面是在老的语言中你可能写的代码 voidprintCollection Collectionc Iteratori c iterator for intk 0 k c size k System out println i next 下面是一个使用泛型的简单尝试 使用了新的循环语法 voidprintCollection Collectionc for Objecte c System out println e 注意 新版本的用处比老版本小多了 老版本的代码可以使用任何类型的Collection作为参数 而新版本则只能使用Collection 我们刚才阐述了 它不是所有类型的Collections的父类 4 通配符 Wildcards 课件制作人 XXX 那么什么是各种Collections的父类呢 它写作 Collection 发音为 collectionofunknown 就是 一个集合 它的元素类型可以匹配任何类型 显然 它被称为通配符 可以写 voidprintCollection Collectionc for Objecte c System out println e 课件制作人 XXX 现在 可以使用任何类型的collection来调用它 注意 仍然可以读取c中的元素 其类型是Object 这是安全的 因为不管collection的真实类型是什么 它包含的都是objects 但是将任意元素加入到其中是不安全的 Collectionc newArrayList c add newObject 编译时错误因为我们不知道c的元素类型 我们不能向其中添加对象 注意 1 add方法有类型参数E作为集合的元素类型 我们传给add的任何参数都必须是一个未知类型的子类 因为我们不知道那是什么类型 所以我们无法传任何东西进去 唯一的例外是null 它是所有类型的成员 2 另一方面 我们可以调用get 方法并使用其返回值 返回值是一个未知的类型 但是我们知道 它总是一个Object 因此把get的返回值赋值给一个Object类型的对象或者放在任何希望是Object类型的地方是安全的 课件制作人 XXX 4 1 有限制的通配 BoundedWildcards 考虑一个简单的画图程序 它可以用来画各种形状 比如矩形和圆形 为了在程序中表示这些形状 你可以定义下面的类继承结构 publicabstractclassShape publicabstractvoiddraw Canvasc publicclassCircleextendsShape privateintx y radius publicvoiddraw Canvasc publicclassRectangleextendsShape privateintx y width height publicvoiddraw Canvasc 课件制作人 XXX 这些类可以在一个画布 Canvas 上被画出来 publicclassCanvas publicvoiddraw Shapes s draw this 所有的图形通常都有很多个形状 假定它们用一个list来表示 Canvas里有一个方法来画出所有的形状会比较方便 4 1 有限制的通配 BoundedWildcards 课件制作人 XXX publicvoiddrawAll Listshapes for Shapes shapes s draw this 现在 类型规则导致drawAll 只能使用Shape的list来调用 它不能 比如说对List来调用 这很不幸 因为这个方法所作的只是从这个list读取shape 因此它应该也能对List调用 我们真正要的是这个方法能够接受一个任意种类的shape publicvoiddrawAll Listshapes 4 1 有限制的通配 BoundedWildcards 课件制作人 XXX 这里有一处很小但是很重要的不同 我们把类型List替换成了List 现在drawAll 可以接受任何Shape的子类的List 所以我们可以对List进行调用 List是有限制通配符的一个例子 这里 代表一个未知的类型 就像前面讲到的通配符一样 但是 在这里 我们知道这个未知的类型实际上是Shape的一个子类 它可以是Shape本身或者Shape的子类而不必是extends自Shape 我们说Shape是这个通配符的上限 upperbound 4 1 有限制的通配 BoundedWildcards 课件制作人 XXX 下面的代码是不允许的 publicvoidaddRectangle Listshapes shapes add 0 newRectangle compile timeerror 为什么上面的代码是不允许的 因为shapes add的第二个参数类型是 extendsShape 一个Shape未知的子类 因此我们不知道这个类型是什么 我们不知道它是不是Rectangle的父类 它可能是也可能不是一个父类 所以这里传递一个Rectangle不安全 4 1 有限制的通配 BoundedWildcards 课件制作人 XXX 5 泛型方法 考虑写一个方法 它用一个Object的数组和一个collection作为参数 完成把数组中所有object放入collection中的功能 下面是第一次尝试 staticvoidfromArrayToCollection Object a Collectionc for Objecto a c add o 编译期错误 现在 应该能够学会避免初学者试图使用Collection作为集合参数类型的错误了 或许你已经意识到使用Collection也不能工作 想一想 你不能把对象放进一个未知类型的集合中去 课件制作人 XXX 解决这个问题的办法是使用genericmethods 就像类型声明 方法的声明也可以被泛型化 就是说 带有一个或者多个类型参数 staticvoidfromArrayToCollection T a Collectionc for To a c add o correct 5 泛型方法 课件制作人 XXX 我们可以使用任意集合来调用这个方法 只要其元素的类型是数组的元素类型的父类Object oa newObject 100 Collectionco newArrayList fromArrayToCollection oa co T指ObjectString sa newString 100 Collectioncs newArrayList fromArrayToCollection sa cs TinferredtobeStringfromArrayToCollection sa co TinferredtobeObjectInteger ia newInteger 100 Float fa newFloat 100 Number na newNumber 100 Collectioncn newArrayList 课件制作人 XXX fromArrayToCollection ia cn TinferredtobeNumberfromArrayToCollection fa cn TinferredtobeNumberfromArrayToCollection na cn TinferredtobeNumberfromArrayToCollection na co TinferredtobeObjectfromArrayToCollection na cs compile timeerror注意 我们并没有传送真实类型参数 actualtypeargument 给一个泛型方法 编译器根据实参为我们推断类型参数的值 它通常推断出能使调用类型正确的最明确的类型参数 原文是 Itwillgenerallyinferthemostspecifictypeargumentthatwillmakethecalltype correct 5 泛型方法 课件制作人 XXX 现在有一个问题 我们应该什么时候使用泛型方法 又什么时候使用通配符类型呢 为了理解答案 让我们先看看Collection库中的几个方法 publicinterfaceCollection booleancontainsAll Collectionc booleanaddAll Collectionc 5 泛型方法 课件制作人 XXX 我们也可以使用泛型方法来代替 publicinterfaceCollection booleancontainsAll Collectionc booleanaddAll Collectionc hey typevariablescanhaveboundstoo 5 泛型方法 课件制作人 XXX 但是 在containsAll和addAll中 类型参数T都只使用一次 返回值的类型既不依赖于类型参数 typeparameter 也不依赖于方法的其他参数 这里 只有简单的一个参数 这告诉我们类型参数 typeargument 被用作多态 polymorphism 它唯一的效果是允许在不同的调用点 可以使用多种实参类型 actualargument 如果是这种情况 应该使用通配符 通配符就是被设计用来支持灵活的子类化的 这是我们在这里要强调的 5 泛型方法 课件制作人 XXX 泛型函数允许类型参数被用来表示方法的一个或多个参数之间的依赖关系 或者参数与其返回值的依赖关系 如果没有这样的依赖关系 不应该使用泛型方法 Genericmethodsallowtypeparameterstobeusedtoexpressdependenciesamongthetypesofoneormoreargumentstoamethodand oritsreturntype Ifthereisn tsuchadependency agenericmethodshouldnotbeused 5 泛型方法 一前一后的同时使用泛型方法和通配符也是可能的 下面是方法Collections copy classCollections publicstaticvoidcopy Listdest Listsrc 注意两个参数的类型的依赖关系 任何被从源list从拷贝出来的对象必须能够将其指定为目标list dest 的元素的类型 T类型
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年秋季学期开学第一课讲稿(班主任)
- 罗湖月嫂培训知识班课件
- 工地疫情期间防控工作措施
- 一年级数学教师备课计划
- 冬季混凝土施工施工流程防冻措施
- 远程消防知识培训课件
- 煤炭销售用户管理办法
- 燃气行业专家管理办法
- 特殊创作人才管理办法
- 特药销售团队管理办法
- 初中语文学习方法指导课件
- 中职教材导游基础知识完整版-PPT课件全套教程
- 烹饪实用英语(第三版)全套课件完整版电子教案最新板
- 实用商务英语教程1509教学课件汇总完整版电子教案
- 市场营销基础第5版电子教案课件
- 外科学教学课件:食管癌与肺癌
- 江苏常熟新材料产业园环境风险评估报告
- 一年级群文阅读学习教案
- 葫芦烙画教学校本课程
- 沙盘规则介绍(课堂PPT)
- 球队赞助策划书(共5页)
评论
0/150
提交评论