Java泛型+数据结构

  1. 泛型

  2. 队列

  3. Iterator 和 ListIterator迭代器

1. 泛型Generics

1.1 泛型的概述

泛型是JDK5.0以后增加的,他可以帮助我们建立类型安全的集合。在使用了泛型的集合中,不必进行强制类型转换。JDK提供了支持泛型的编译器,将运行时的类型检查提前到了编译时执行,使代码可读性和安全性更高。

代码示例:

  • 不使用泛型时,会在程序运行时期检查元素的类型是否为String,强转不当会出现类型转换异常

  •  

     

  •  

    ​ 说明: 集合添加了泛型后,可以在编译时期约束元素的类型,对编程有指导作用。

    1.1.1 泛型的引入

    在JDK1.5之前,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。

    我们先看下面的代码: 

 

以上示例中,向list类型集合中加入了一个String类型的值和一个Integer类型的值。在之后的循环中,由于在list中加入了Integer类型的值,如果直接做强转操作会抛出java.lang.ClassCastException异常。为了解决这个问题,泛型应运而生。  

1.1.2 泛型的使用

泛型的本质就是“数据类型的参数化”。 我们可以把“泛型”理解为类型的一个占位符(形式参数),即告诉编译器,在调用泛型时必须传入实际类型。

【示例】泛型的使用案例

 

泛型的出现避免了强制转换的麻烦,同时把运行时期的ClassCastException异常提前到编译时期。

1.1.3 泛型擦除补偿

java分两个部分,编译和运行,泛型的出现提高了编译的安全性,正因为编译时检查完了,运行时才没事。因此泛型本质上是编译时期的技术,是给编译器用的。

程序在运行时,会将泛型擦除掉(擦除之后的类型就是Object类型),这个称为泛型擦除。

为什么要擦除呢?为了兼容运行的类加载器!运行的时候,要靠虚拟机启动类装载器,专门读取类文件解析类文件,并把类文件加载进内存的程序。JDK1.4版本,JDK1.5版本都用的这个加载器。程序只在编译的时候,将类型进行检查。如果检查完是安全的,没有错误的,运行就可以把这个泛型去掉了,因为类型就统一了。我们还想要以前的类加载器进行加载解析,并进内存。

有一个问题,取出来的时候不加强转了,你还知道取出来的是什么吗?编译器只做检查,检查完,最终这个类型被擦掉,所以这个里面和以前一样还是object,(这里应该是指,add方法中加入的元素变成了object类型了),那就意味着它们提升了。同时,下面还不能做强转,取出来就能用,这是为什么呢?

这里又做了另外一种动作:在运行时,通过获取元素的实际类型进行强制,叫做补偿(不必手动实现强制转换)。编译结束后,要是完全不告诉类装载器不合适,用了泛型补偿机制告诉类加载器,都检测完了,就编写一个补偿程序。在类装载器已有的基础上,来了以后,我根据你指定的好的元素类型,真正运行的时候就要碰到这个元素了,根据你的元素获取其类型,再对你进行一次转换就行了。


 

1.2 泛型的使用

​ 泛型,用来灵活地将数据类型应用到不同的类、方法、接口当中,将数据类型作为参数进行传递。

1.2.1 含有泛型的类

定义格式:修饰符 class 类名<代表泛型的变量> { }

【示例】泛型类的定义

使用格式:创建对象时,确定泛型的类型

【示例】泛型类的使用  

此时,变量 E 的值就是 Integer 类型。

注意:静态方法不能使用类上定义的泛型。

1.2.2 含有泛型的方法

定义格式:修饰符 <代表泛型的变量> 返回值类型 方法名(形参列表){}

【示例】泛型方法的定义

 

使用格式:调用方法时,确定泛型的类型。

【示例】泛型方法的使用

 

 

注意:泛型对象只能使用Object类中的方法,不能使用其特有的方法。

1.2.3 含有泛型的接口

定义格式:修饰符 interface 接口名<代表泛型的变量> { }

【示例】泛型接口的定义

使用格式:

1、 定义类时确定泛型的类型。

 

此时,变量 E 的值就是 String 类型。

2、始终不确定泛型的类型,直到创建对象时,确定泛型的类型。

 

此时,变量 E 的值就是 Integer类型。

1.2.4 泛型通配符

​ 泛型是在限定数据类型,当在集合或者其他地方使用到泛型后,那么这时一旦明确泛型的数据类型,那么在使用的时候只能给其传递和数据类型匹配的类型,否则就会报错。

​ 有的时候,我们在定义方法时,根本无法确定具体集合中的元素类型是什么。为了解决这个“无法确定具体集合中的元素类型”问题,java 中,为我们提供了泛型的通配符。

通配符的几种形式:

1、无限定通配符,<?>。

2、上限通配符,<? extends Number>。表示参数类型只能是Number及其子类。

3、下限通配符,<? supper Number>。表示参数类型只能是Number及其父类。

【示例】无限定通配符案例

 

 

说明:上面的示例代码中,print()方法的参数使用了通配符,得以传入泛型类Student <E>任意类型的参数。如果,将通配符改成具体的一种类型,例如String类型。那print()方法就只能传入泛型类Student <String>类型的参数。

【示例】上限通配符案例

 

 

【示例】下限通配符案例  

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值