Java中的泛型是一种在编译时提供类型安全检查的机制,它允许程序员在类、接口或方法中使用类型参数(type parameters)。使用泛型可以使代码更加灵活,同时避免了在运行时的类型错误和不必要的类型转换。
1. 泛型的基本概念
泛型的核心概念是在类、接口或方法定义时不指定具体的类型,而是使用一个或多个类型参数代替。当实例化类或调用方法时,指定具体的类型参数。
示例:定义一个泛型类
public class Box<T> {
private T t; // T代表一个未知类型
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
}
在这个例子中,T
是一个类型参数,它将在创建 Box
类的实例时被实际的类型替换。
2. 使用泛型
示例:实例化一个泛型类
Box<Integer> integerBox = new Box<Integer>();
integerBox.set(123);
Integer someInteger = integerBox.get();
Box<String> stringBox = new Box<String>();
stringBox.set("hello");
String someString = stringBox.get();
3. 泛型方法
你可以在方法级别上定义泛型,无论这个方法是在泛型类中还是普通类中。
示例:定义一个泛型方法
public class Util {
public static <T> void print(T t) {
System.out.println(t.toString());
}
}
// 使用泛型方法
Util.<String>print("Hello");
Util.print(10); // 类型推断
4. 通配符
Java 泛型中的通配符 ?
允许你创建更加灵活的代码。例如,你可以使用 ? extends T
来表示类型的上界(type upper bound),表示参数化类型可能是 T 或 T 的子类。
示例:使用通配符
public void processElements(List<? extends Number> elements) {
for (Number n : elements) {
System.out.println(n);
}
}
5. 泛型的限制
- 类型擦除:Java 泛型是通过类型擦除来实现的。这意味着泛型信息只存在于编译阶段,在进入 JVM 之前,与泛型相关的类型信息将被擦除,替换为原始类型(raw type)。
- 静态环境限制:由于类型擦除,你不能在静态字段或方法中引用类型参数。
- 异常限制:你不能捕获或抛出一个泛型类的实例。
6. 类型推断
从Java 7开始,Java增加了类型推断的能力,使得你在使用泛型类和方法时可以省略明确的类型参数。
示例:类型推断
Box<Integer> box = new Box<>(); // Java 7及以上版本支持的钻石语法
泛型是Java中一个复杂但极其有用的特性,合理使用可以大大提高程序的可读性和安全性。