什么是泛型? 在Java中,泛型是一种在编译时检查类型安全性的机制。它允许程序员编写方法或类,其中的数据类型可以在运行时确定。这使得代码更加灵活和可重用。 泛型的基本用法 泛型的基本用法包括定义泛型类和泛型方法。 定义泛型类
public class Box<T> {
private T item;
public Box(T item) {
this.item = item;
}
public T getItem() {
return item;
}
public void setItem(T item) {
this.item = item;
}
}
public class Main {
public static void main(String[] args) {
Box<String> stringBox = new Box<>("Hello");
String s = stringBox.getItem(); // 编译器自动类型检查
}
}
在这个例子中,Box 类使用了一个类型参数 T,表示它可以存储任何类型的对象。当创建 Box 对象时,必须指定具体的类型,例如 Box 表示存储字符串的对象。
public class Utility {
public static <T> void swap(T[] array, int i, int j) {
T temp = array[i];
array[i] = array[j];
array[j] = temp;
}
public static void main(String[] args) {
Integer[] numbers = {1, 2, 3};
swap(numbers, 0, 2); // 编译器自动类型检查
System.out.println(Arrays.toString(numbers)); // 输出 [3, 2, 1]
}
}
在这个例子中,swap 方法使用了一个类型参数 T,表示它可以交换任何类型的数组元素。当调用 swap 方法时,编译器会自动推断类型参数 T。
泛型的限制 有时候我们需要对泛型添加一些限制,以便更好地利用类型特性。 泛型的上界 使用 extends 关键字可以指定泛型的上界。
public class UpperBound<T extends Number> {
private T item;
public UpperBound(T item) {
this.item = item;
}
public T getItem() {
return item;
}
public void setItem(T item) {
this.item = item;
}
}
public class Main {
public static void main(String[] args) {
UpperBound<Integer> integerBox = new UpperBound<>(10);
// UpperBound<String> stringBox = new UpperBound<>("Hello"); // 错误,String 不是 Number 的子类
}
}
在这个例子中,UpperBound 类的类型参数 T 必须是 Number 的子类。 泛型的下界 使用 super 关键字可以指定泛型的下界。
public class LowerBound<T super Number> {
private T item;
public LowerBound(T item) {
this.item = item;
}
public T getItem() {
return item;
}
public void setItem(T item) {
this.item = item;
}
}
public class Main {
public static void main(String[] args) {
LowerBound<Number> numberBox = new LowerBound<>(new Number() {});
// LowerBound<String> stringBox = new LowerBound<>("Hello"); // 错误,String 不是 Number 的超类
}
}
在这个例子中,LowerBound 类的类型参数 T 必须是 Number 的超类。 泛型擦除 Java中的泛型是编译时的概念,在运行时会被擦除(erasure)。这意味着在运行时,所有的泛型类型都会被替换为其对应的原始类型。
public class GenericExample<T> {
private T item;
public T getItem() {
return item;
}
public void setItem(T item) {
this.item = item;
}
}
public class Main {
public static void main(String[] args) {
GenericExample<String> stringBox = new GenericExample<>();
stringBox.setItem("Hello");
String s = stringBox.getItem(); // 编译器自动类型检查
// 在运行时,stringBox 实际上是一个 GenericExample<Object>
Object obj = stringBox.getItem(); // 运行时类型为 Object
}
}
尽管编译器能够进行类型检查,但在运行时泛型类型会被擦除,因此只能访问其原始类型。 总结 Java中的泛型提供了一种强大的类型安全机制,使代码更加灵活和可重用。通过定义泛型类和泛型方法,可以轻松地处理不同类型的数据。同时,通过添加泛型的上下界限制,可以进一步增强类型的安全性和灵活性。理解泛型擦除的概念有助于更好地理解Java中的类型系统和内存管理。