Java的泛型程序设计

来源:互联网 发布:java删除指定文件 编辑:程序博客网 时间:2024/06/02 03:58

泛型是常见的程序设计手段,使用泛型机制编写的程序代码要比杂乱地使用Object变量,然后再进行强制类型转换的代码更具的安全性和可读性。

一、泛型程序设计

泛型程序设计意味着编写的代码可以被很多不同类型的对象所重用。

1>在Java中增加泛型类之前,泛型程序设计是用继承实现的。ArrayList类只维护一个Object引用的数组。

2>泛型通过类型参数来指示元素的类型。这比使用Object类型的参数安全一些,而且编译器可以进行检查,避免插入错误类型的对象。

注:出现编译错误比类在运行时出现类的强制类型转换异常要好得多。

二、定义简单泛型类

一个泛型类就是具有一个或多个类型变量的类。

public class Student<T, U> {private T name;private U age;public T getName() {return name;}public void setName(T name) {this.name = name;}public U getAge() {return age;}public void setAge(U age) {this.age = age;}}
1>类型变量使用尖括号<>括起来,并放在类名的后面。泛型类可以有多个类型变量。

2>类定义中的类型变量指定方法的返回类型以及域和局部变量的类型。

3>类型变量使用大写形式,且比较短,这是很常见的。在Java库中,使用变量E表示集合的元素类型,K和V分别表示表的关键字与值的类型。T(需要时还可以使用临近字母U和S)表示“任意类型”。

4>用具体的类型替换类型变量就可以实例化泛型类。

三、泛型方法

public static <T> T getMiddle(T... a){return a[a.length/2];}
泛型方法,即可以定义在普通类中,也可以定义在泛型类中。

注:类型变量放在修饰符(public static)的后面,返回类型的前面。

1>当调用一个泛型方法时,在方法名前的尖括号中放入具体的类型。

四、类型变量的限定

public static <T extends Comparable> T min(T[] a)

1>使用extends关键字,而不是implements的原因(如上:Comparable是接口,但是却使用extends)

表示T应该是绑定类型的子类型,T和绑定类型可以是类,也可以是接口。选择关键字extends的原因是更接近子类的概念,并且Java的设计者也不打算在语言中再添加一个新的关键字

2>一个类型变量或通配符可以有多个限定,限定类型用”&“分隔,而逗号用来分隔类型变量。

五、泛型代码和虚拟机

1>虚拟机没有泛型类型对象------所有对象都属于普通类。

2>无论何时定义了一个泛型类型,都自动提供了一个相应的原始类型,原始类型的名字就是删去类型参数后的泛型类型名。擦除类型变量,并替换为限定类型(无限定的变量用Object)。

( 1 )翻译泛型表达式

1>对于表达式: Employee buddy = buddies.getFirst();

a>擦除方法的返回类型后,返回Object类型。

b>编译器自动插入Employee的强制类型转换,将Object类型强制转换为Employee类型。

注:对于插入数据的方法,也是类似过程。

( 2 )翻译泛型方法

1>完整的泛型方法族: public static <T extends Comparable> T min(T[] a)

如果擦除类型参数T为: public static Comparable min(Comparable[] a)  ,类型参数擦除后只留下限定类型Comparable。

注:如果在子类中类型擦除与多态可能发生冲突,解决办法使用桥方法。

a>虚拟机中没有泛型,只有普通的类和方法。

b>所有的类型参数都用他们的限定类型替换。

c>桥方法被合成来保持多态。

d>为保持类型安全性,必要时插入强制类型转换。

( 3 )调用遗留代码

设计Java泛型类型时,主要目标是运行泛型代码和遗留代码之间相互操作。

( 4 )约束与局限性

Java泛型有一些限制。大多数是由类型擦除引起的。

1>不能用基本类型实例化类型参数

2>运行时类型查询只适用于原始类型

如:a instanceof Pair<String> 实际上就是仅仅测试a是否是任意类型的Pair

同样getClass方法总是返回原始类型,即Pair,与类型参数无关。

3>不能创建参数化类型的数组。

如:Pair<String>[] table = new Pair<String>[10];

如果需要收集参数化类型对象,只有一种安全而有效的方法:使用ArrayList:ArrayList<Pair<String>>

4>不能实例化类型变量。即:new T()这样的表达式。

可以使用Class<T> cl的方式cl.newInstance()。

5>泛型类的静态上下文中类型变量无效。

禁止使用带有类型变量的静态域和方法。

6>不能抛出或捕获泛型类的实例。

7>注意擦除后的冲突。

( 5 )泛型类型的继承规则

Pair<Manager>并不是Pair<Employee>的子类

泛型类可以扩展或实现其他的泛型类。

注:本章节未学习完成,在有需要的时候重温学习。
0 0
原创粉丝点击