您的位置:首页 > 编程语言 > Java开发

Java 学习笔记——泛型

2015-10-14 15:55 253 查看
1. 定义一个泛型类

class Pair<T> {
private T first;
private T second;

public Pair() {
first = null;
second = null;
}

public Pair(T first, T second) {
this.first = first;
this.second = second;
}

public void setFirst(T first) {
this.first = first;
}

public T getFirst() {
return first;
}

public void setSecond(T second) {
this.second = second;
}

public T getSecond() {
return second;
}

}

    类型变量 T 表示任意类型(也可以用临近的字母 U、S 表示),Java 中使用 E 表示集合元素类型,K,V 分别表示表的 关键字和值 类型。可以定义多个类型变量如 class Pair<T,U>{ ... } 类型变量用逗号隔开。

2. 定义泛型方法

@SuppressWarnings("unchecked")
public static <T> T getMiddle(T... a) {
return a[a.length / 2];
}

3. 限定类型变量

public static <T extends Comparable<T>> T min(T[] a) {
if (a == null || a.length == 0)
return null;
T smallest = a[0];
for (int i = 1; i < a.length; i++)
if (smallest.compareTo(a[i]) > 0)
smallest = a[i];
return smallest;
}

    如果限定多个类型,则用符号 & 隔开,如 <T extends Comparable<T> & Serializable>,限定类型的顺序影响类型擦除后表示的类型,取第一个限定类型作为擦除后类型。比如 <T extends Comparable<T> & Serializable> 类型擦除后会用 Comparable 类替换 T。

4. 泛型类的类型擦除

    在 Java 虚拟机中,不存在泛型类型对象,所有的对象都属于普通的类。定义一个泛型类型,会自动提供一个对应的原始类型,原始类型名是去掉泛型类型变量后的类名,并擦除类型变量,替换成限定的类型(没有限定类型就是 Object)。比如 Pair<T> 泛型类的原始类型是:

class Pair {
private Object first;
private Object second;

public Pair() {
first = null;
second = null;
}

public Pair(Object first, Object second) {
this.first = first;
this.second = second;
}

public void setFirst(Object first) {
this.first = first;
}

public Object getFirst() {
return first;
}

public void setSecond(Object second) {
this.second = second;
}

public Object getSecond() {
return second;
}

}

    当程序调用泛型方法时,会先调用原始类型的方法,再强制类型转换成需要的类型。如:Pair<Employee> buddies = new Pair<Employee>();
Employee employee = buddies.getFirst();

    buddies.getFirst() 返回 Object 类型,然后强制转换成 Employee 类型

5. 泛型方法的类型擦除

    泛型方法的类型擦除也是把类型变量转换成限定类型,无限定类型就是 Object,如:// 泛型方法
public void <T> method(T extends Comparable param) {}
// 类型擦除后
public void Comparable method(Comparable param){}    如果泛型类的子类想要覆盖父类方法,编译器会在子类中生成一个桥方法,用于实现覆盖父类方法,例如:
class DateInterval extends Pair<Date> {
@Override
public void setSecond(Date second) {
if (second.compareTo(getFirst()) >= 0)
super.setSecond(second);
}
}
    编译器会在 DateInterval 类中生成桥方法
public void setSecond(Object second) {
setSecond((Date)second);
}


    通过桥方法实现覆盖父类的 setSecond 方法。原因是 DateInterval 类在类型擦除后,从父类继承的 setSecond 方法是:public void setSecond(Object second){},而自身的setSecond(Date
second){} 并没有覆盖掉父类的 setSecond 方法(方法名相同,方法参数(顺序、类型)不同,属于方法重载),所以编译器通过桥方法实现方法的覆盖。

6. 通配符

    符号 ? 表示通配符,使用通配符为泛型类指定子类型和父类型,例如
Pair<Manager> 是 Pair<? extendsEmployee> 的子类,而 Pair<Manager> 和 Pair<Employee> 之间并没有关系,虽然 Manager 是 Employee 的子类。Pair<?
super Manager> 用于指定父类。

    注:通配符不是类型变量,比如 Pair<?> 的 ? getFirst() 是非法的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java 泛型