深入java 认识泛型及其用法

来源:互联网 发布:qq飞车紫焰战神数据 编辑:程序博客网 时间:2024/05/29 08:54

这篇文章转载java序列化和反序列化过程中,值得注意的一些细节问题。更多的源代码请访问我的github:https://github.com/yangsheng20080808/deepIntoJava

本文分为4大部分

  • 我们为什么需要泛型
  • 泛型类和自定义泛型类
  • 泛型方法和自定义泛型方法

我们为什么需要泛型

在jdk1.5之前,我们想要在一些集合中添加同类的元素,一般是怎么做呢?只能通过
1. Object 是所有类型的父类
2. 类型强制转换
这两个特点的配合来实现泛型的功能,这样实现的泛型功能要在程序运行期才能知道 Object 真正的对象类型,在 javac 编译期,编译器无法检查这个 Object 的强制转型是否成功,这便将一些风险转接到了程序运行期中,很有可能会出现:ClassCastException(类型转化错误。)
我们举例子说明:
这里写图片描述

但是该错误只能在运行期间才能发现,程序能够正常的通过编译,并不会报错。其实我们应该尽快通知程序员。
这里写图片描述

泛型是一种语法糖,它出现可以确保集合类安全的使用和改正集合类的类型安全弱点。(关于什么是语法糖我们可以见下方)

 语法糖(Syntactic Sugar),也称糖衣语法,是由英国计算机学家 Peter.J.Landin 发明的一个术语,指在计算机语言中添加的某种语法。 目标:这种语法对语言的功能并没有影响,但是更方便程序员使用。Java 中最常用的语法糖主要有泛型、变长参数、条件编译、自动拆装箱、内部类等。 JVM虚拟机并不支持这些语法,它们在编译阶段就被还原回了简单的基础语法结构,这个过程成为解语法糖。

java在jdk1.5之后,引入的泛型实际上只在程序源码(我们的java文件)中存在,在编译后的字节码文件(编译后得到的class文件)中,就已经被替换为了原来的原生类型,并且在相应的地方插入了强制转型代码,因此对于运行期的Java语言来说,ArrayList和 ArrayList就是同一个类。所以泛型技术实际上是 Java 语言的一颗语法糖,Java 语言中的泛型实现方法称为类型擦除,基于这种方法实现的泛型被称为伪泛型。

举个例子说明:
这里写图片描述
我们用idea自带的反编译工具反编译的结果是:
这里写图片描述
集合在声明的时候类型被替换为了原来的原生类型,并且在相应的地方插入了强制转型代码
用了泛型后假如我们想加入别的类型,在编译器就会报错
这里写图片描述

泛型最主要的优点就是让编译器追踪参数类型,执行类型检查和类型转换:编译器保证类型转换不会失败。

如果依赖程序员去追踪对象类型和执行转换,那么运行时产生的错误将很难去定位和调试,然而有了泛型,编译器 可以帮助我们执行大量的类型检查,并且可以检测出更多的编译时错误。

泛型类和自定义泛型类

我们在java的集合类中应该会经常见到泛型类,List

public interface List<E> extends Collection<E>

如果考虑参数化一个类,请考虑是否满足以下条件:
一个核心类位于某种包装器的中心:也就是说,类中心的 “东西” 可广泛地应用,它周围的特性(例如属性)是相同的。
行为是相同的:无论类中心的 “东西” 是什么,都会执行完全相同的操作。

根据这两个条件,可以看到集合满足以下要求:
这个 “东西” 就是组成集合的类。
操作(比如 add、remove、size 和 clear)完全相同,无论集合由哪些对象组成。

我们可以自定义一个自己的泛型类(我写的例子不满足上述规范):
这里写图片描述

泛型方法和自定义泛型方法

如果我们在泛型类里面定义泛型方法,那么类型直接用就好,但是假如我们的类不是泛型类同时我们又想声明泛型方法,需要在方法体声明泛型;举例子说明:

public class MyClass {// Other possible stuff... ignore...  public <E> String formatArray(E[] arrayToFormat) {    StringBuilder sb = new StringBuilder();    int index = 0;    for (E element : arrayToFormat) {      sb.append("Element ");      sb.append(index++);      sb.append(" => ");      sb.append(element);      sb.append('\n');    }    return sb.toString();  }// More possible stuff... ignore...}

无需参数化 MyClass,可以将您想要使用的一个方法泛型化,创建一个适合任何元素类型的一致的字符串表示。

**特别注意:我们的迭代器模式,只要实现Iteratable接口并返回Iterator就可以支持泛型,其中只要我们实现了这个接口,系统就会给我们foreach的语法糖。详细可以看:http://liuzxc.github.io/blog/java-advance-06/
http://blog.csdn.net/andie_guo/article/details/12871733(这一篇更好)**

原创粉丝点击