泛型
泛型的概念
泛型是 Java 5 引入的一个新特性,它提供了编译时类型安全检测机制,该机制允许在编译时检测到非法的类型。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
泛型类
泛型类是在定义类时使用泛型。以下是一个简单的泛型类示例:
java
// 定义一个泛型类
class Box<T> {
private T t;
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
}
public class GenericClassExample {
public static void main(String[] args) {
// 创建一个存储 Integer 类型的 Box 对象
Box<Integer> integerBox = new Box<>();
integerBox.set(10);
Integer num = integerBox.get();
System.out.println("Integer value: " + num);
// 创建一个存储 String 类型的 Box 对象
Box<String> stringBox = new Box<>();
stringBox.set("Hello");
String str = stringBox.get();
System.out.println("String value: " + str);
}
}
在上述代码中,Box
类是一个泛型类,T
是类型参数。在创建 Box
对象时,可以指定具体的类型,如 Integer
或 String
。
泛型接口
泛型接口与泛型类的定义和使用方式类似。以下是一个泛型接口的示例:
java
// 定义一个泛型接口
interface Generator<T> {
T next();
}
// 实现泛型接口
class FruitGenerator implements Generator<String> {
private String[] fruits = {"Apple", "Banana", "Cherry"};
private int index = 0;
@Override
public String next() {
if (index < fruits.length) {
return fruits[index++];
}
return null;
}
}
public class GenericInterfaceExample {
public static void main(String[] args) {
FruitGenerator generator = new FruitGenerator();
String fruit = generator.next();
while (fruit != null) {
System.out.println(fruit);
fruit = generator.next();
}
}
}
在这个例子中,Generator
是一个泛型接口,FruitGenerator
类实现了该接口并指定了具体的类型为 String
。
泛型方法
泛型方法是在定义方法时使用泛型。以下是一个泛型方法的示例:
java
public class GenericMethodExample {
// 定义一个泛型方法
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.print(element + " ");
}
System.out.println();
}
public static void main(String[] args) {
// 创建一个 Integer 数组
Integer[] intArray = {1, 2, 3, 4, 5};
// 创建一个 String 数组
String[] stringArray = {"Hello", "World"};
// 调用泛型方法打印 Integer 数组
printArray(intArray);
// 调用泛型方法打印 String 数组
printArray(stringArray);
}
}
在上述代码中,printArray
是一个泛型方法,它可以接受任何类型的数组作为参数。
泛型的好处
- 类型安全:泛型的主要目标是提高 Java 程序的类型安全。通过使用泛型,编译器可以在编译时检查类型错误,避免在运行时出现
ClassCastException
。 - 代码复用:泛型允许编写通用的代码,这些代码可以处理不同类型的数据,从而提高了代码的复用性。
- 可读性:泛型代码更具可读性,因为它清楚地表明了所处理的数据类型。
泛型的通配符
在使用泛型时,有时需要使用泛型通配符来表示未知类型。Java 提供了三种通配符:
- 无界通配符
<?>
:表示未知类型。例如,List<?>
表示一个元素类型未知的列表。 - 上界通配符
<? extends T>
:表示类型是T
或T
的子类。例如,List<? extends Number>
表示一个元素类型是Number
或其子类的列表。 - 下界通配符
<? super T>
:表示类型是T
或T
的父类。例如,List<? super Integer>
表示一个元素类型是Integer
或其父类的列表。
以下是一个使用通配符的示例:
java
import java.util.ArrayList;
import java.util.List;
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
public class WildcardExample {
// 使用上界通配符
public static void printAnimals(List<? extends Animal> animals) {
for (Animal animal : animals) {
System.out.println(animal);
}
}
public static void main(String[] args) {
List<Dog> dogs = new ArrayList<>();
dogs.add(new Dog());
dogs.add(new Dog());
List<Cat> cats = new ArrayList<>();
cats.add(new Cat());
cats.add(new Cat());
printAnimals(dogs);
printAnimals(cats);
}
}
在这个例子中,printAnimals
方法使用了上界通配符 <? extends Animal>
,这意味着它可以接受任何元素类型是 Animal
或其子类的列表。