在 Java 中,泛型 (Generics) 允许你编写类型安全且具有可复用性的代码。泛型类和泛型方法是 Java 泛型编程的两个关键概念。
1. 泛型类(Generic Class)
泛型类允许类在定义时不指定具体的类型,而是通过类型参数来使类能够处理不同类型的数据。这使得类可以在实例化时指定所需的类型。
示例:泛型类
// 定义一个泛型类 Box
public class Box<T> {
private T value;
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
使用泛型类
public class Main {
public static void main(String[] args) {
// 创建一个类型为 Integer 的 Box
Box<Integer> integerBox = new Box<>();
integerBox.setValue(10);
System.out.println("Integer Value: " + integerBox.getValue());
// 创建一个类型为 String 的 Box
Box<String> stringBox = new Box<>();
stringBox.setValue("Hello Generics!");
System.out.println("String Value: " + stringBox.getValue());
}
}
输出:
Integer Value: 10
String Value: Hello Generics!
2. 泛型方法(Generic Method)
泛型方法是指在方法中使用泛型,而不仅仅是在类中。即使是在没有泛型类的情况下,你也可以为方法指定类型参数。
示例:泛型方法
public class GenericMethodExample {
// 定义一个泛型方法,返回类型和参数类型都使用了类型参数 T
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.println(element);
}
}
public static void main(String[] args) {
// 使用泛型方法处理不同类型的数组
Integer[] intArray = {1, 2, 3, 4, 5};
String[] stringArray = {"Hello", "World"};
printArray(intArray); // 输出 Integer 数组
printArray(stringArray); // 输出 String 数组
}
}
输出:
1
2
3
4
5
Hello
World
3. 泛型方法的定义和调用
public static <T> void printArray(T[] array)
:<T>
是方法的类型参数,它声明了一个泛型类型T
,使得该方法可以接受任意类型的数组。T[]
表示方法的参数是一个泛型数组,类型为T
。- 返回类型是
void
,即方法没有返回值。
- 调用方法时,
T
会被具体的类型替代(例如:Integer[]
或String[]
)。
4. 通配符(Wildcard)与泛型
泛型可以使用通配符(?
)来指定一种未知的类型。常用的通配符有:
?
:表示任何类型。? extends T
:表示类型是T
或T
的子类型。? super T
:表示类型是T
或T
的父类型。
示例:使用通配符
import java.util.List;
public class WildcardExample {
public static void printNumbers(List<? extends Number> list) {
for (Number num : list) {
System.out.println(num);
}
}
public static void main(String[] args) {
List<Integer> intList = List.of(1, 2, 3, 4);
List<Double> doubleList = List.of(1.1, 2.2, 3.3);
printNumbers(intList); // 输出 Integer 类型的列表
printNumbers(doubleList); // 输出 Double 类型的列表
}
}
输出:
1
2
3
4
1.1
2.2
3.3
在这个例子中,List<? extends Number>
表示 list
可以是 Number
类型或其子类型(如 Integer
或 Double
)的列表。
5. 多个类型参数
Java 允许在一个类或方法中使用多个类型参数。例如:
public class Pair<T, U> {
private T first;
private U second;
public Pair(T first, U second) {
this.first = first;
this.second = second;
}
public T getFirst() {
return first;
}
public U getSecond() {
return second;
}
}
public class Main {
public static void main(String[] args) {
Pair<Integer, String> pair = new Pair<>(1, "One");
System.out.println("First: " + pair.getFirst());
System.out.println("Second: " + pair.getSecond());
}
}
在这个例子中,Pair
类使用了两个类型参数:T
和 U
,它们分别表示存储的两个不同类型的元素。
6. 泛型的限制
泛型类型参数有时可能需要满足某些条件(如继承自某个类或实现某个接口)。这种约束通过 通配符边界 来实现。
示例:使用 extends
限制泛型类型
public class GenericClass<T extends Number> {
private T value;
public GenericClass(T value) {
this.value = value;
}
public T getValue() {
return value;
}
}
在这个例子中,T extends Number
表示 T
必须是 Number
类的子类或 Number
本身。
总结
- 泛型类:可以定义类时使用类型参数,使得类可以处理不同类型的数据。
- 泛型方法:方法中可以使用类型参数,使得方法能够接受和返回不同类型的数据。
- 通配符:使用
?
、? extends T
或? super T
来指定未知类型或限制泛型类型的范围。 - 多个类型参数:可以在类或方法中使用多个类型参数来提供更灵活的泛型支持。
- 类型限制:可以使用
extends
来限制泛型类型参数的范围,确保它们符合某个类型的要求。