泛型(Generics)的概念
泛型是Java语言的一种特性,它允许在编译时定义类、接口和方法的类型参数,从而实现代码的复用和类型安全。通过泛型,可以编写更加通用和安全的代码。
类型擦除(Type Erasure)的概念
类型擦除是Java泛型实现的一种机制。在编译时,泛型类型参数会被擦除,并替换为它们的上限(通常是Object
),除非指定了上限。类型擦除确保了泛型代码与非泛型代码的兼容性。
通配符(Wildcard)和边界(Bounds)的使用
通配符和边界可以用来增强泛型的灵活性,主要有以下几种形式:
- 无界通配符(Unbounded Wildcard):
- 使用
?
表示无界通配符,表示可以是任何类型。 - 适用于只读操作,不适用于写操作。
- 示例:
List<?> list = new ArrayList<String>();
- 使用
- 上界通配符(Upper Bounded Wildcard):
- 使用
? extends T
表示上界通配符,表示类型必须是T
或T
的子类。 - 适用于读操作,不适用于写操作。
- 示例:
List<? extends Number> list = new ArrayList<Integer>();
- 使用
- 下界通配符(Lower Bounded Wildcard):
- 使用
? super T
表示下界通配符,表示类型必须是T
或T
的父类。 - 适用于写操作,不适用于读操作。
- 示例:
List<? super Integer> list = new ArrayList<Number>();
- 使用
- 边界通配符(Bounded Wildcard):
- 使用
? extends T
或? super T
表示边界通配符,可以指定类型的上限或下限。 - 示例:
List<? extends Comparable<?>> list = new ArrayList<String>();
- 使用
示例
以下是一个简单的示例,展示了如何使用泛型、通配符和边界:
import java.util.ArrayList;
import java.util.List;
public class GenericsExample {
public static void main(String[] args) {
// 无界通配符
List<?> list1 = new ArrayList<String>();
// list1.add("Hello"); // 编译错误,不能添加元素
// 上界通配符
List<? extends Number> list2 = new ArrayList<Integer>();
// list2.add(123); // 编译错误,不能添加元素
Number number = list2.get(0); // 可以读取元素
// 下界通配符
List<? super Integer> list3 = new ArrayList<Number>();
list3.add(123); // 可以添加元素
// Integer integer = list3.get(0); // 编译错误,不能保证类型安全
// 边界通配符
List<? extends Comparable<?>> list4 = new ArrayList<String>();
// list4.add("Hello"); // 编译错误,不能添加元素
Comparable<?> comparable = list4.get(0); // 可以读取元素
}
}
在这个示例中,我们展示了如何使用无界通配符、上界通配符、下界通配符和边界通配符来增强泛型的灵活性。
总结
泛型通过类型参数提供了代码的复用和类型安全。类型擦除是Java泛型的实现机制,确保了泛型代码与非泛型代码的兼容性。通配符和边界可以用来增强泛型的灵活性,适用于不同的使用场景。