Java 泛型类、泛型方法、泛型接口
泛型类
使用时需通过<具体类型>
指定泛型参数的实际类型(不支持基本数据类型,需用包装类,如int
→Integer
)
泛型类的类型参数在编译时会被 “类型擦除”:编译器将泛型参数替换为Object
(或上限类型),因此运行时不存在 “泛型类型”(如GenericClass<String>
和GenericClass<Integer>
在运行时是同一个类)。
不能在静态成员中使用泛型类的类型参数(静态成员属于类,初始化时泛型类型未确定)。
public class GenericClass<T> {
// 错误:静态成员不能使用泛型类的T
// private static T staticData;
}
泛型方法
泛型方法是在方法定义时声明 “类型参数”,与类是否是泛型类无关。
// 语法:[访问修饰符] <类型参数1, 类型参数2, ...> 返回值类型 方法名(参数列表) { ... }
// 关键:类型参数声明(<T>)必须在返回值类型之前
public class GenericMethodDemo {
// 泛型方法:打印任意类型的数组
public <T> void printArray(T[] array) {
for (T element : array) {
System.out.print(element + " ");
}
System.out.println();
}
// 泛型方法:返回两个元素中的较大值(需限制T为Comparable子类)
public <T extends Comparable<T>> T getMax(T a, T b) {
return a.compareTo(b) >= 0 ? a : b;
}
}
泛型接口
实现泛型接口的两种方式
方式 1:实现接口时指定具体类型
// 实现GenericInterface,指定T为String类型
public class StringProcessor implements GenericInterface<String> {
private String result;
@Override
public void process(String data) {
// 处理String类型数据(如转为大写)
result = data.toUpperCase();
}
@Override
public String getResult() {
return result;
}
}
// 使用
StringProcessor processor = new StringProcessor();
processor.process("hello");
System.out.println(processor.getResult()); // 输出:HELLO
方式 2:实现接口时保留泛型(成为 “泛型实现类”)
// 实现GenericInterface,保留T作为泛型参数
public class GenericProcessor<T> implements GenericInterface<T> {
private T result;
@Override
public void process(T data) {
// 通用处理逻辑(如直接保存数据)
this.result = data;
}
@Override
public T getResult() {
return result;
}
}
// 使用时指定具体类型
GenericProcessor<Integer> intProcessor = new GenericProcessor<>();
intProcessor.process(100);
System.out.println(intProcessor.getResult()); // 输出:100
GenericProcessor<Double> doubleProcessor = new GenericProcessor<>();
doubleProcessor.process(3.14);
System.out.println(doubleProcessor.getResult()); // 输出:3.14
泛型支持通过extends
和super
限制类型参数的范围,避免传入不合法的类型。
public class NumberBox<T extends Number> {
}
public <T super Integer> void addIntegerToCollection(T element, Collection<T> collection) {
collection.add(element);
}
泛型通配符的三种形式
(1)无界通配符(?
)
表示 “未知的任意类型”,适用于 “只读取集合元素,不添加元素” 的场景(因为无法确定元素类型,添加任何类型都可能不安全)。
// 定义接收“任意泛型List”的方法(无界通配符)
public void printList(List<?> list) {
for (Object obj : list) { // 只能用Object接收元素(未知类型)
System.out.print(obj + " ");
}
System.out.println();
}
// 使用:可传入任意泛型的List
List<String> strList = Arrays.asList("a", "b", "c");
List<Integer> intList = Arrays.asList(1, 2, 3);
List<Double> doubleList = Arrays.asList(1.1, 2.2);
printList(strList); // 输出:a b c
printList(intList); // 输出:1 2 3
printList(doubleList); // 输出:1.1 2.2
// 注意:无界通配符的List不能添加元素(除了null)
List<?> unknownList = new ArrayList<String>();
unknownList.add(null); // 允许(null是所有类型的默认值)
// unknownList.add("hello"); // 错误:无法确定类型,添加不安全
(2)上限通配符(? extends 父类型
)
表示 “未知类型,但必须是父类型的子类或父类型本身”,适用于 “只读取元素,不添加元素” 的场景(与无界通配符类似,但能限制元素的上限类型,支持调用父类型方法)。
// 定义接收“泛型为Number子类的List”的方法(上限通配符)
public double sumList(List<? extends Number> list) {
double sum = 0.0;
for (Number num : list) { // 可用Number接收元素(上限类型)
sum += num.doubleValue(); // 调用Number的方法(安全)
}
return sum;
}
// 使用:可传入List<Integer>、List<Double>等(都是Number的子类)
List<Integer> intList = Arrays.asList(10, 20, 30);
List<Double> doubleList = Arrays.asList(1.5, 2.5);
List<Number> numberList = Arrays.asList(5, 10.5);
System.out.println(sumList(intList)); // 输出:60.0
System.out.println(sumList(doubleList)); // 输出:4.0
System.out.println(sumList(numberList)); // 输出:15.5
// 注意:上限通配符的List也不能添加元素(除了null)
List<? extends Number> numList = new ArrayList<Integer>();
// numList.add(10); // 错误:无法确定numList的具体类型(可能是List<Double>)
(3)下限通配符(? super 子类型
)
表示 “未知类型,但必须是子类型的父类型或子类型本身”,适用于 “只添加元素,不读取元素” 的场景(能确定添加的元素类型是子类型,父类型集合可安全接收)。
// 定义向“泛型为Integer父类型的List”添加元素的方法(下限通配符)
public void addIntegers(List<? super Integer> list) {
list.add(10); // 允许添加Integer(子类型)
list.add(20);
list.add(new Integer(30));
}
// 使用:可传入List<Integer>、List<Number>、List<Object>(都是Integer的父类型)
List<Integer> intList = new ArrayList<>();
List<Number> numberList = new ArrayList<>();
List<Object> objList = new ArrayList<>();
addIntegers(intList); // intList变为[10,20,30]
addIntegers(numberList); // numberList变为[10,20,30]
addIntegers(objList); // objList变为[10,20,30]
// 注意:下限通配符的List读取元素时,只能用Object接收(未知父类型的具体类型)
for (Object obj : numberList) {
System.out.print(obj + " "); // 输出:10 20 30
}
分类:
Java-Backend
标签:
Java
版权申明
本文系作者 @xiin 原创发布在To Future$站点。未经许可,禁止转载。
暂无评论数据