`
longgangbai
  • 浏览: 7331345 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

泛型的学习总结

阅读更多

  泛型的学习总结

     Java 代码介绍泛型类型(generic type)和支持它们的特性,描述诸如基本类型的限制、受限泛型和多态方法之类的 Tiger 特性来说明泛型类型的优缺点(即将发表的专栏文章将讨论其它特性,比如 Tiger 中泛型类型的特定表现以及可能扩展为 Tiger 之外的泛型类型)。

数据类型转换和错误

      为理解泛型类型为何如此有用,我们要将注意力转向 Java 语言中最容易引发错误的因素之一 - 需要不断地将表达式向下类型转换(downcast)为比其静态类型更为具体的数据类型(请参阅 参考资料中的“The Double Descent bug pattern”,以了解进行数据类型转换时,可能会碰到的麻烦的某些方面)。

        程序中的每个向下类型转换对于 ClassCastException 而言都是潜在的危险,应当尽量避免它们。但是在 Java 语言中它们通常是无法避免的,即便在设计优良的程序中也是如此。

       在 Java 语言中进行向下类型转换最常见的原因在于,经常以专用的方式来使用类,这限制了方法调用所返回的参数可能的运行时类型。例如,假定往 Hashtable 中添加元素并从中检索元素。那么在给定的程序中,被用作键的元素类型和存储在散列表中的值类型,将不能是任意对象。通常,所有的键都是某一特定类型的实例。同样地,存储的值将共同具有比 Object 更具体的公共类型。

        但是在目前现有的 Java 语言版本中,不可能将散列表的特定键和元素声明为比 Object 更具体的类型。在散列表上执行插入和检索操作的类型特征符告诉我们只能插入和删除任意对象。

 

 

    Java 类型系统相当薄弱,因此代码会因象上面那样的数据类型转换而漏洞百出。这些数据类型转换不仅使 Java 代码变得更加拖沓冗长,而且它们还降低了静态类型检查的价值(因为每个数据类型转换都是一个选择忽略静态类型检查的伪指令)。我们该如何扩展该类型系统,从而不必回避它呢?

 

 

用泛型类型来解决问题!

           要消除如上所述的数据类型转换,有一种普遍的方法,就是用 泛型类型来增大 Java 类型系统。可以将泛型类型看作是类型“函数”;它们通过类型变量进行参数化,这些类型变量可以根据上下文用各种类型参数进行 实例化

例如,与简单地定义类 Hashtable 不同,我们可以定义泛型类 Hashtable<Key, Value> ,其中 KeyValue 是类型参数。除了类名后跟着尖括号括起来的一系列类型参数声明之外,在 Tiger 中定义这样的泛型类的语法和用于定义普通类的语法很相似。例如,可以按照如下所示的那样定义自己的泛型 Hashtable 类:

 

定义泛型 Hashtable 类

Hashtable<Key, Value>

可以引用这些类型参数,就像我们在类定义主体内引用普通类型那样

类型参数的作用域就是相应类定义的主体部分(除了静态成员之外)。

创建一个新的 Hashtable 实例时,必须传递类型参数以指定 KeyValue 的类型。传递类型参数的方式取决于我们打算如何使用 Hashtable

 

Tiger 的基本类型限制

        Tiger 中类型变量的限制之一就是,它们必须用引用类型进行实例化 - 基本类型不起作用。因此,在上面这个示例中,无法完成创建从 int 映射到 StringHashtable

这很遗憾,因为这意味着只要您想把基本类型用作泛型类型的参数,您就必须把它们组装为对象。另一方面,当前的这种情况是最糟的;您不能将 int 作为键传递给 Hashtable ,因为所有的键都必须是 Object 类型。

我们真正想看到的是,基本类型可以自动进行包装(boxing)和解包装(unboxing),类似于用 C# 所进行的操作(或者比后者更好)。遗憾的是,Tiger 不打算包括基本类型的自动包装(但是人们可以一直期待 Java 1.6 中出现该功能!)。

 

 

受限泛型

               有时我们想限制可能出现的泛型类的类型实例化。在上面这个示例中,类 Hashtable 的类型参数可以用我们想用的任何类型参数进行实例化,但是对于其它某些类,我们或许想将可能的类型参数集限定为给定类型 范围内的子类型。

例如,我们可能想定义泛型 ScrollPane 类,它引用普通的带有滚动条功能的 Pane 。被包含的 Pane 的运行时类型通常会是类 Pane 的子类型,但是静态类型就只是 Pane

有时我们想用 getter 检索被包含的 Pane ,但是希望 getter 的返回类型尽可能具体些。我们可能想将类型参数 MyPane 添加到 ScrollPane 中,该类型参数可以用 Pane 的任何子类进行实例化。然后可以用这种形式的子句: extends Bound 来说明 MyPane 的声明,从而来设定 MyPane 的范围:

 

class ScrollPane<MyPane extends Pane> { ... }

当然,我们可以完全不使用显式的范围,只要能确保没有用不适当的类型来实例化类型参数。

 

为什么要自找麻烦在类型参数上设定范围呢?

这里有两个原因。

首先,范围使我们增加了静态类型检查功能。有了静态类型检查,就能保证泛型类型的每次实例化都符合所设定的范围。

其次,因为我们知道类型参数的每次实例化都是这个范围之内的子类,所以可以放心地调用类型参数实例出现在这个范围之内的任何方法。如果没有对参数设定显式的范围,那么缺省情况下范围是 Object ,这意味着我们不能调用范围实例在 Object 中未曾出现的任何方法。

 

多态方法

       除了用类型参数对类进行参数化之外,用类型参数对方法进行参数化往往也同样很有用。泛型 Java 编程用语中,用类型进行参数化的方法被称为 多态方法(Polymorphic method)

     

      多态方法之所以有用,是因为有时候,在一些我们想执行的操作中,参数与返回值之间的类型相关性原本就是泛型的,但是这个泛型性质不依赖于任何类级的类型信息,而且对于各个方法调用都不相同。

           例如,假定想将 factory 方法添加到 List 类中。这个静态方法只带一个参数,也将是 List 唯一的元素(直到添加了其它元素)。因为我们希望 List 成为其所包含的元素类型的泛型,所以希望静态 factory 方法带有类型变量 T 这一参数并返回 List<T> 的实例。

           但是我们确实希望该类型变量 T 能在方法级别上进行声明,因为它会随每次单独的方法调用而发生改变(而且,正如我在下一篇文章中将讨论的那样,Tiger 设计的“怪习”规定静态成员不在类级类型参数的范畴之内)。Tiger 让我们通过将类型参数作为方法声明的前缀,从而在单独的方法级别上声明类型参数。例如,可以按照如下所示的那样为 factory 方法 make 添加前缀:

 

<T extends Object> public static List<T> make(T first) {
     return new List<T>(first);
   }

                  除了多态方法中所增加的灵活性之外,Tiger 中还增加了一个优点。

          Tiger 使用类型推断机制,根据参数类型来自动推断出多态方法的类型。这可以大大减少方法调用的繁琐和复杂性。

在 Java 语言中添加泛型类型肯定会大大增强我们使用静态类型系统的能力。学习如何使用泛型类型相当简单,但是同样也需要避免一些缺陷。

 

非泛型ArrayList的缺点:
      1:处理值类型时,出现装箱、折箱操作,影响性能。_list.Add(1)时会发生装箱。 
      2:处理引用类型时,虽没有装箱和折箱操作,但仍需要类型转换操作。代码_list.Add("a")不会发生装箱。
      3:程序运行时的类型转换可能引发异常。运行_list[1]时,由于它是一个字符串,要强制转换成int就会有异常

 

public <T extends Object> void thisIsT(List <T> list){

}



public void thisIsP(List <? extends Object> list){

}

<T extends Collection>其中,限定了构造此类实例的时候T是一个确定类型(具体类型),这个类型实现了Collection接口,
但是实现 Collection接口的类很多很多,如果针对每一种都要写出具体的子类类型

 

<? extends Collection>其中,?是一个未知类型,是一个通配符泛型,这个类型是实现Collection接口即可。

 

T 是一种类型。
?是泛指(就是通配符)

?是表示这是个未知的类型,而最终用T,就是指定要把这个未知的类给实例化,以便用这个类中的方法或者参数.

 

泛型处理过程:泛型用一个通用的数据类型T来代替object,在类实例化时指定T的类型,CLR自动编译为本地代码,并且保证数据类型安全。

     泛型优点:

     1:类型安全的。例如实例化了int类型的类,就不能处理string类型的数据。上面的_list2.Add("a"),就会报错。

     2:处理值类型时,无需装箱和折箱。int j=i+1;i可以直接取,并不需要折箱操作。
     3:无需类型转换,包含值类型和引用类型
 

泛型类实例化的理论:

    泛型类在编译时,先生成中间代码,通用类型T只是一个占位符。在实例化类时,根据用户指定的数据类型代替T并由即时编译器(JIT)生成本地代码,这个本地代码中已经使用了实际的数据类型。

分享到:
评论

相关推荐

    java基础-泛型学习总结

    思维导图

    泛型思维导图

    泛型学习总结思维导图,个人学习总结,不完善,仅供参考,持续完善中

    个人学习C#泛型总结ppt

    C#泛型是一种强大的编程工具,它为C#程序员提供了更大的灵活性和性能优化。泛型在.NET Framework 2.0中被引入,旨在解决传统集合类(如ArrayList)在处理不同类型数据时存在的性能和类型安全问题。以下是关于C#泛型...

    泛型笔记学习2009

    #### 总结 泛型是Java语言的一项重要特性,它极大提升了代码的类型安全性和可读性,同时也为开发人员提供了一种更为灵活的方式来处理不同类型的数据。通过合理使用泛型,可以有效地避免常见的类型转换错误,并且编写...

    java基础泛型 学习全文件

    总结,Java基础泛型的学习涵盖了类型参数、泛型类、方法和接口,以及边界、类型擦除、多态和集合的使用等多个方面。理解并熟练运用泛型,可以显著提升代码的质量和可维护性。在实际开发中,特别是在处理数据结构如...

    Java泛型编程最全总结

    Java泛型是Java编程语言中的一个关键特性,它在2004年随着JDK 5.0的发布被引入,极大地增强了代码的类型安全性和重用性。泛型允许我们在编写类...通过深入学习和实践,我们可以更高效地利用泛型来设计和实现复杂系统。

    Java泛型学习【转自百度百科】

    总结,Java泛型提供了强大的类型约束能力,使代码更加健壮和高效。理解和掌握泛型的用法对于编写高质量的Java程序至关重要。在实际开发中,合理运用泛型能有效提升代码的可维护性和安全性,减少潜在的运行时错误。

    java泛型学习

    ### Java泛型学习知识点 #### 一、泛型的基本概念及意义 - **引入背景**:JDK 5.0 引入了泛型的概念,这是为了提高 Java 的类型安全性而进行的重要改进。泛型使得程序员能够在编程时指定类型参数,从而避免运行时...

    Java泛型深入学习和总结 看这一篇就足够!

    二 泛型类、泛型接口、泛型方法、泛型通配符 2.1 泛型类: 2.2 泛型接口: 2.3 泛型方法: 2.4 泛型通配符: 三 限定类型变量 四 泛型中的约束和局限性 4.1 不能用基本类型实例化类型参数 4.2 运行时类型查询只适用...

    java技术之泛型的学习

    总结,Java中的泛型是提高代码质量和可维护性的重要工具。理解和熟练使用泛型能帮助开发者编写出更安全、更高效、更易于维护的代码。通过深入学习和实践,我们可以更好地利用泛型这一强大的特性,提升我们的编程技能...

    C__泛型的运用

    ### C# 泛型的应用详解 #### 一、泛型的概念 ...通过学习和掌握泛型的基本概念和用法,开发者可以编写更加高效、可维护的代码。无论是对于初学者还是资深开发人员来说,熟练掌握泛型都是提升编程技能的重要一步。

    全面总结Java泛型

    Java 泛型是 Java 编程语言中一个强大的特性,它允许在类、接口和方法中使用类型参数,从而增加了代码的复用性...无论 Martin Odersky 对 Java 泛型有何评价,学习并掌握这一特性对于任何 Java 开发者来说都是必要的。

    C++泛型编程,学习总结方便回看!

    C++泛型编程,联系代码手稿。容器、模版、STL:string、vector、deque、stack、queue、list、map、set,函数对象:仿函数、谓词、常见库算法:遍历、查找、排序

    Webservice传递泛型的案例,包括web服务端和mobile端

    Web服务是IT领域中一种广泛使用的通信协议,它允许不同应用程序之间交换数据。...通过学习和实践这个案例,开发者将能够更好地理解和应用泛型在Web服务和移动开发中的作用,从而提高代码的复用性和安全性。

    java泛型.xmind

    自己总结的java泛型的笔记,绘制了详细的思维导图,每个思维导图中均有详细的博文解释,方便大家学习和理解,免费分享给大家。适合java的爱好者和学习者

    C#泛型、委托与事件解析

    总结一下,C#的泛型提供了类型安全的容器,减少了类型转换的需要;委托允许我们传递方法作为参数,实现了回调和事件处理;事件则为对象间通信提供了一种安全、解耦的方式,特别是在用户界面设计中。熟练掌握这些概念...

    集合与泛型

    ### 集合与泛型知识点总结 #### 泛型概览 - **引入原因**:在Java 1.5及之后的版本中,引入了泛型这一特性,旨在提高集合类使用的安全性与灵活性。主要解决的问题包括: - **元素存储的安全性问题**:在非泛型...

    C#泛型 调研报告 C#泛型

    5. **总结** C#泛型提供了一种强大的工具,使得开发者能够在保持类型安全的同时,编写出更加通用、高性能的代码。理解并熟练运用泛型是提高C#开发效率和代码质量的关键,它不仅简化了代码,也降低了维护成本,尤其...

    Java1.5泛型指南中文版.doc

    ### Java 1.5 泛型指南中文版知识点解析 #### 1. 引言 在Java 1.5中引入的泛型是一种强大的类型安全机制,它允许开发者...这些知识点涵盖了从基础到高级的泛型使用技巧,对于学习和应用Java泛型具有重要的指导意义。

    C__2.0中泛型编程初级入门教程

    因此,学习如何在 C# 2.0 中利用泛型进行编程是非常有价值的。 #### 二、为什么使用泛型? 在 C# 1.x 版本中,如果想要创建一个可以处理多种类型的通用类或方法,常见的做法是使用 Object 类型作为参数。但是这样...

Global site tag (gtag.js) - Google Analytics