Java 泛型(Generics)是 Java 5 引入的一种特性,允许在类、接口和方法中定义类型参数。泛型的使用提供了类型安全、可重用性和灵活性。下面将对 Java 泛型进行详细说明,包括其基本概念、语法、优势和使用示例。
1. 基本概念
- 类型参数:在泛型中,类型参数是在定义类、接口或方法时使用的占位符。常见的类型参数包括
<T>
,<E>
,<K, V>
等。 - 泛型类和接口:通过定义类型参数,可以创建对不同类型的实例进行操作的类和接口。
2. 泛型的语法
2.1 定义泛型类
public class Box<T> {
private T item;
public void setItem(T item) {
this.item = item;
}
public T getItem() {
return item;
}
}
在这个示例中,Box
类是一个泛型类,其中 T
是类型参数,可以代表任何引用类型。
2.2 定义泛型方法
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.print(element + " ");
}
}
这个 printArray
方法是一个泛型方法,<T>
表示该方法是泛型的,T
可以是任何类型。
3. 泛型的使用示例
3.1 使用泛型类
public class Main {
public static void main(String[] args) {
Box<String> stringBox = new Box<>();
stringBox.setItem("Hello, Generics!");
System.out.println(stringBox.getItem());
Box<Integer> integerBox = new Box<>();
integerBox.setItem(123);
System.out.println(integerBox.getItem());
}
}
在这个例子中,我们创建了不同类型的 Box
实例:Box<String>
和 Box<Integer>
。
3.2 使用泛型方法
public class Main {
public static void main(String[] args) {
Integer[] intArray = {
1, 2, 3, 4, 5 };
String[] strArray = {
"Hello", "World" };
printArray(intArray);
printArray(strArray);
}
}
4. 泛型的优势
类型安全:泛型提供了更高的类型安全性,避免了强制转换的错误,编译器会在编译时检查类型。
代码重用:使用泛型可以编写一次代码,而在多种数据类型上进行重用,减少了重复代码。
消除强制类型转换:泛型允许在使用时避免强制类型转换,从而使代码更简洁和安全。
5. 类型边界
在定义泛型时,可以使用类型边界来限制类型参数。
5.1 上界通配符
public static <T extends Number> void processNumbers(T number) {
System.out.println("Number: " + number);
}
// 使用
processNumbers(10); // Integer
processNumbers(10.5); // Double
在这个例子中,T extends Number
表明 T
必须是 Number
类或其子类。
5.2 下界通配符
public static void addNumbers(List<? super Integer> list) {
list.add(10); // 可以添加 Integer 类型
}
// 使用
List<Number> numbers = new ArrayList<>();
addNumbers(numbers);
6. 通配符
通配符(Wildcard)是泛型的一种特殊用法,使用 ?
符号表示。
- 无界通配符:
List<?>
可以接收任何类型的 List。 - 上界通配符:
List<? extends Number>
可以接收Number
类型及其子类的 List。 - 下界通配符:
List<? super Integer>
可以接收Integer
类型及其父类的 List。
7. 泛型与集合框架
Java 的集合框架广泛使用泛型。例如,ArrayList<T>
, HashMap<K, V>
等,都利用了泛型来实现类型安全的集合存储。
List<String> list = new ArrayList<>();
list.add("Hello");
String item = list.get(0); // 无需强制转换
8. 注意事项
- 泛型不能被实例化:不能创建类型参数的实例,例如
T obj = new T();
是非法的。 - 无法使用基本数据类型:不能直接使用基本数据类型(如
int
、char
),需要使用其包装类(如Integer
、Character
)。 - 类型擦除:Java 泛型在编译时实现,运行时不保留泛型类型的信息,这称为类型擦除。
总结
Java 泛型为编程提供了灵活性和类型安全,减少了重复代码,提高了代码的可读性和可维护性。通过理解泛型的基本概念、语法和使用技巧,开发者可以有效地利用 Java 泛型来设计出更高效的程序。