泛型是 Java 中一项重要的特性,它允许在定义类、接口和方法时使用类型参数,从而实现代码的复用和类型安全。下面是关于 Java 泛型的使用教程:
一、泛型的基本概念
泛型(Generics)的核心思想是将类型参数化,即在定义类、接口或方法时不指定具体类型,而是在使用时再指定。这样可以:
- 提高代码复用性
- 保证类型安全,避免 ClassCastException
- 减少类型转换操作
二、泛型类
泛型类是在类定义时使用类型参数的类。
语法:
class 类名<T> {
// 可以使用T作为类型
private T value;
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
示例:
// 定义泛型类
class Box<T> {
private T content;
public T getContent() {
return content;
}
public void setContent(T content) {
this.content = content;
}
}
// 使用泛型类
public class Main {
public static void main(String[] args) {
// 创建存储String类型的Box
Box<String> stringBox = new Box<>();
stringBox.setContent("Hello Generics");
String str = stringBox.getContent(); // 无需类型转换
// 创建存储Integer类型的Box
Box<Integer> intBox = new Box<>();
intBox.setContent(123);
int num = intBox.getContent();
}
}
三、泛型接口
泛型接口与泛型类类似,在接口定义时指定类型参数。
语法:
interface 接口名<T> {
T method();
}
示例:
// 定义泛型接口
interface Generator<T> {
T generate();
}
// 实现泛型接口
class NumberGenerator implements Generator<Integer> {
@Override
public Integer generate() {
return (int)(Math.random() * 100);
}
}
四、泛型方法
泛型方法是在方法定义时声明类型参数的方法,它可以在普通类或泛型类中定义。
语法:
修饰符 <T> 返回值类型 方法名(参数列表) {
// 方法体
}
示例:
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[] intArray = {
1, 2, 3, 4, 5};
String[] stringArray = {
"Hello", "World", "Generics"};
printArray(intArray); // 自动推断类型为Integer
printArray(stringArray); // 自动推断类型为String
}
}
五、泛型通配符
泛型通配符用于表示未知类型,主要有三种形式:
?
:表示任意类型? extends T
:表示T类型或T的子类型(上界限定)? super T
:表示T类型或T的父类型(下界限定)
示例:
public class WildcardExample {
// 只能读取,不能写入
public static void printList(List<? extends Number> list) {
for (Number n : list) {
System.out.print(n + " ");
}
System.out.println();
}
// 可以写入T类型及其子类型
public static void addNumbers(List<? super Integer> list) {
for (int i = 1; i <= 5; i++) {
list.add(i);
}
}
public static void main(String[] args) {
List<Integer> intList = new ArrayList<>();
List<Double> doubleList = new ArrayList<>();
List<Object> objList = new ArrayList<>();
printList(intList); // 合法
printList(doubleList); // 合法
addNumbers(intList); // 合法
addNumbers(objList); // 合法
}
}
六、泛型的限制
- 不能使用基本类型作为类型参数,必须使用包装类
- 泛型类型参数不能用于静态成员
- 不能实例化泛型类型的对象
- 不能使用
instanceof
检查泛型类型
七、泛型擦除
Java 泛型是通过类型擦除实现的,在编译时会将泛型信息擦除,替换为原始类型(通常是Object)。这意味着运行时不保留泛型类型信息。
理解泛型擦除有助于理解一些泛型的特殊行为和限制。
通过上述内容,你应该对 Java 泛型有了基本的了解。泛型在集合框架中应用广泛,熟练掌握泛型的使用可以提高代码的质量和可维护性。