知识大全 轻松掌握 Java 泛型 (第 1 部分)

Posted 类型

篇首语:恢弘志士之气,不宜妄自菲薄。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 轻松掌握 Java 泛型 (第 1 部分)相关的知识,希望对你有一定的参考价值。

轻松掌握 Java 泛型 (第 1 部分)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  J SE - 代号为 Tiger - 计划在 年年底发布 我一直都热衷于尽可能多地收集有关即将推出的新技术的预告信息 因此我将撰写一系列的文章 讨论可从 V 中获得的新的和经过重组的特性 本文是第一篇 我特别想谈谈泛型类型并重点讲述在 Tiger 中为了支持它们而进行的更改和调整     在许多方面 Tiger 肯定是迄今为止在 Java 编程方面(包括对源语言语法的重大扩展)所取得的最大进步 Tiger 中计划进行的最显著的变化是添加泛型类型 正如在 JSR 原型编译器中所预先展示的那样(您可以立即免费下载该编译器 请参阅参考资料)     让我们从介绍泛型类型是什么以及添加了什么特性来支持它们开始吧      数据类型转换和错误  为理解泛型类型为何如此有用 我们要将注意力转向 Java 语言中最容易引发错误的因素之一 - 需要不断地将表达式向下类型转换(downcast)为比其静态类型更为具体的数据类型(请参阅参考资料中的 The Double Descent bug pattern 以了解进行数据类型转换时 可能会碰到的麻烦的某些方面)     程序中的每个向下类型转换对于 ClassCastException 而言都是潜在的危险 应当尽量避免它们 但是在 Java 语言中它们通常是无法避免的 即便在设计优良的程序中也是如此     在 Java 语言中进行向下类型转换最常见的原因在于 经常以专用的方式来使用类 这限制了方法调用所返回的参数可能的运行时类型 例如 假定往 Hashtable 中添加元素并从中检索元素 那么在给定的程序中 被用作键的元素类型和存储在散列表中的值类型 将不能是任意对象 通常 所有的键都是某一特定类型的实例 同样地 存储的值将共同具有比 Object 更具体的公共类型     但是在目前现有的 Java 语言版本中 不可能将散列表的特定键和元素声明为比 Object 更具体的类型 在散列表上执行插入和检索操作的类型特征符告诉我们只能插入和删除任意对象 例如 put 和 get 操作的说明如下所示     清单 插入/检索类型说明表明只能是任意对象    class Hashtable    Object put(Object key Object value)    Object get(Object key)           因此 当我们从类 Hashtable 的实例检索元素时 比如 即使我们知道在 Hashtable 中只放了 String 而类型系统也只知道所检索的值是 Object 类型 在对检索到的值进行任何特定于 String 的操作之前 必须将它强制转换为 String 即使是将检索到的元素添加到同一代码块中 也是如此!    清单 将检索到的值强制转换成 String    import java util Hashtable;  class Test    public static void main(String[] args)     Hashtable h = new Hashtable();    h put(new Integer( ) value );    String s = (String)h get(new Integer( ));    System out println(s);         请注意 main 方法主体部分的第三行中需要进行的数据类型转换 因为 Java 类型系统相当薄弱 因此代码会因象上面那样的数据类型转换而漏洞百出 这些数据类型转换不仅使 Java 代码变得更加拖沓冗长 而且它们还降低了静态类型检查的价值(因为每个数据类型转换都是一个选择忽略静态类型检查的伪指令) 我们该如何扩展该类型系统 从而不必回避它呢?     用泛型类型来解决问题!  要消除如上所述的数据类型转换 有一种普遍的方法 就是用泛型类型来增大 Java 类型系统 可以将泛型类型看作是类型 函数 它们通过类型变量进行参数化 这些类型变量可以根据上下文用各种类型参数进行实例化     例如 与简单地定义类 Hashtable 不同 我们可以定义泛型类 Hashtable< Key, Value> 其中 Key 和 Value 是类型参数 除了类名后跟着尖括号括起来的一系列类型参数声明之外 在 Tiger 中定义这样的泛型类的语法和用于定义普通类的语法很相似 例如 可以按照如下所示的那样定义自己的泛型 Hashtable 类     清单 定义泛型 Hashtable 类    class Hashtable< Key, Value>     然后可以引用这些类型参数 就像我们在类定义主体内引用普通类型那样 如下所示     清单 像引用普通类型那样引用类型参数 class Hashtable< Key, Value>        Value put(Key k Value v)    Value get(Key k)       类型参数的作用域就是相应类定义的主体部分(除了静态成员之外)(在下一篇文章中 我们将讨论为何 Tiger 实现中有这样的 怪习 即必须对静态成员进行此项限制 请留意!)     创建一个新的 Hashtable 实例时 必须传递类型参数以指定 Key 和 Value 的类型 传递类型参数的方式取决于我们打算如何使用 Hashtable 在上面的示例中 我们真正想要做的是创建 Hashtable 实例 它只将 Integer 映射为 String 可以用新的 Hashtable 类来完成这件事     清单 创建将 Integer 映射为 String 的实例    import java util Hashtable;  class Test    public static void main(String[] args)     Hashtable< Integer, String> h = new Hashtable< Integer, String>();    h put(new Integer( ) value );              现在不再需要数据类型转换了 请注意用来实例化泛型类 Hashtable 的语法 就像泛型类的类型参数用尖括号括起来那样 泛型类型应用程序的参数也是用尖括号括起来的     清单 除去不必要的数据类型转换       String s = h get( key );  System out println(s);    当然 程序员若只是为了能使用泛型类型而必须重新定义所有的标准实用程序类(比如 Hashtable 和 List)的话 则可能会是一项浩大的工程 幸好 Tiger 为用户提供了所有 Java 集合类的泛型版本 因此我们不必自己动手来重新定义它们了 此外 这些类能与旧代码和新的泛型代码一起无缝工作(下个月 我们会说明如何做到这一点)      Tiger 的基本类型限制  Tiger 中类型变量的限制之一就是 它们必须用引用类型进行实例化 - 基本类型不起作用 因此 在上面这个示例中 无法完成创建从 int 映射到 String 的 Hashtable     这很遗憾 因为这意味着只要您想把基本类型用作泛型类型的参数 您就必须把它们组装为对象 另一方面 当前的这种情况是最糟的 您不能将 int 作为键传递给 Hashtable 因为所有的键都必须是 Object 类型     我们真正想看到的是 基本类型可以自动进行包装(boxing)和解包装(unboxing) 类似于用 C# 所进行的操作(或者比后者更好) 遗憾的是 Tiger 不打算包括基本类型的自动包装(但是人们可以一直期待 Java 中出现该功能!)      受限泛型  有时我们想限制可能出现的泛型类的类型实例化 在上面这个示例中 类 Hashtable 的类型参数可以用我们想用的任何类型参数进行实例化 但是对于其它某些类 我们或许想将可能的类型参数集限定为给定类型范围内的子类型     例如 我们可能想定义泛型 ScrollPane 类 它引用普通的带有滚动条功能的 Pane 被包含的 Pane 的运行时类型通常会是类 Pane 的子类型 但是静态类型就只是 Pane     有时我们想用 getter 检索被包含的 Pane 但是希望 getter 的返回类型尽可能具体些 我们可能想将类型参数 MyPane 添加到 ScrollPane 中 该类型参数可以用 Pane 的任何子类进行实例化 然后可以用这种形式的子句 extends Bound 来说明 MyPane 的声明 从而来设定 MyPane 的范围     清单 用 extends 子句来说明 MyPane 声明    class ScrollPane< MyPane extends Pane>     当然 我们可以完全不使用显式的范围 只要能确保没有用不适当的类型来实例化类型参数     为什么要自找麻烦在类型参数上设定范围呢?这里有两个原因 首先 范围使我们增加了静态类型检查功能 有了静态类型检查 就能保证泛型类型的每次实例化都符合所设定的范围     其次 因为我们知道类型参数的每次实例化都是这个范围之内的子类 所以可以放心地调用类型参数实例出现在这个范围之内的任何方法 如果没有对参数设定显式的范围 那么缺省情况下范围是 Object 这意味着我们不能调用范围实例在 Object 中未曾出现的任何方法      多态方法  除了用类型参数对类进行参数化之外 用类型参数对方法进行参数化往往也同样很有用 泛型 Java 编程用语中 用类型进行参数化的方法被称为多态方法(Polymorphic method)     多态方法之所以有用 是因为有时候 在一些我们想执行的操作中 参数与返回值之间的类型相关性原本就是泛型的 但是这个泛型性质不依赖于任何类级的类型信息 而且对于各个方法调用都不相同     例如 假定想将 factory 方法添加到 List 类中 这个静态方法只带一个参数 也将是 List 唯一的元素(直到添加了其它元素) 因为我们希望 List 成为其所包含的元素类型的泛型 所以希望静态 factory 方法带有类型变量 T 这一参数并返回 List< T> 的实例     但是我们确实希望该类型变量 T 能在方法级别上进行声明 因为它会随每次单独的方法调用而发生改变(而且 正如我在下一篇文章中将讨论的那样 Tiger 设计的 怪习 规定静态成员不在类级类型参数的范畴之内) cha138/Article/program/Java/JSP/201311/19766

相关参考

知识大全 Java泛型编程之诀窍

Java泛型编程之诀窍  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  &nb

知识大全 Java的泛型原来这样让人不舒服

Java的泛型原来这样让人不舒服  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  Java泛型中的

知识大全 java中使用泛型

  泛型是在jdk之后才出现的一种机制说简单点就是一个特定的对象可以接收任何的对象例如杯子可以装水也可以装饮料说简单点就是来者不拒什么都要下面我就来写个小例子看一下  写一个接口Info里面什么方法都

知识大全 Java高级编程——泛型类型 第一部分

Java高级编程——泛型类型第一部分  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  编辑按《Ja

知识大全 Java编程思想里的泛型实现一个堆栈类 分享

Java编程思想里的泛型实现一个堆栈类分享  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  觉得作

知识大全 Java5泛型 T.class的获取和为擦拭法站台

Java5泛型T.class的获取和为擦拭法站台  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  

知识大全 Java运行时监控,第1部分: Java运行时性能和可用性监控

Java运行时监控,第1部分:Java运行时性能和可用性监控  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看

知识大全 深入Java调试体系: 第1部分,JPDA体系概览

深入Java调试体系:第1部分,JPDA体系概览  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  

知识大全 安全技术 Java与安全性,第1部分一

安全技术Java与安全性,第1部分一  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  WebLog

知识大全 安全技术 Java与安全性,第1部分二(图)

安全技术Java与安全性,第1部分二(图)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  用户和