一、概述
Java 泛型(Generics)是 JDK 5 引入的一个新特性,它提供了一种编译时类型安全检测机制,允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
二、使用泛型的好处
- 类型安全:泛型允许在编译时检测到非法的类型。
- 消除类型转换:使用泛型后,大多数情况下可以自动进行类型转换,避免繁琐的强制类型转换。
- 提高代码的重用性:通过泛型,可以编写出更通用的代码,适用于多种数据类型。
- 性能优势:通过类型擦除,泛型代码在运行时与原生代码无异,没有性能损失。
三、泛型类
泛型类是指具有一个或多个类型参数的类。在定义类时,类型参数被指定在类名后面,使用尖括号<>
包围。
public class Box<T> {
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
}
在这个例子中,T
是一个类型参数,用于指定Box
类中可以存储的对象类型。
四、泛型接口
泛型接口与泛型类的定义类似,也是在接口名后添加类型参数。
public interface Pair<K, V> {
public K getKey();
public V getValue();
}
这里定义了一个泛型接口Pair
,它有两个类型参数K
和V
,分别用于指定键和值的类型。
五、泛型方法
泛型方法是指可以应用于多种类型的方法。在方法返回类型前声明泛型参数。
public class Util {
public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
return p1.getKey().equals(p2.getKey()) && p1.getValue().equals(p2.getValue());
}
}
这里定义了一个泛型方法compare
,它接受两个Pair
对象作为参数,并比较它们的键和值是否相等。<K, V>
是方法的类型参数,它们与Pair
接口的类型参数相对应。
六、类型通配符
在泛型中,?
被称为通配符。它表示未知的类型。当你不确定或不想指定泛型中的具体类型时,可以使用通配符。
?
:表示未知的类型。? extends T
:表示未知的类型,但它是T
或T
的子类。? super T
:表示未知的类型,但它是T
或T
的父类。
七、类型擦除
泛型信息只存在于编译时,在运行时,Java 的虚拟机(JVM)中并没有泛型类型的相关信息。这个过程被称为类型擦除(Type Erasure)。类型擦除的主要机制是擦除泛型类型中的类型参数,替换为类型参数的上限(通常是Object
)。
八、注意事项
- 泛型类不能创建静态泛型数组,因为泛型类型在运行时会被擦除为
Object
,无法确定具体类型。 - 泛型方法中的类型参数与类的类型参数无关,它们是两个完全不同的概念。
- 泛型中的基本数据类型会被自动包装为其对应的包装类(如
int
变为Integer
)。
九、总结
Java 泛型是一个强大的特性,它提供了编译时类型检查,避免了类型转换的错误,提高了代码的重用性和安全性。掌握泛型的使用,对于编写高质量、易于维护的Java代码至关重要。