范型super和extends关键字的区别
# super
super 关键字用于指定泛型类型参数的下界(lower bound),也就是指定泛型类型参数必须是某个特定类型的超类或者该特定类型本身。 使用 super 时,泛型类型参数可以向上转型为其下界类型,这意味着你可以安全地将一个泛型类型参数赋值给其下界类型的变量。
例如:
public static void printList(List<? super Integer> list) {
for (Object elem : list) {
System.out.print(elem + " ");
}
System.out.println();
}
List<Number> nums = new ArrayList<>();
nums.add(1);
nums.add(2.0);
printList(nums); // 输出: 1 2.0
List<Object> objs = new ArrayList<>();
objs.add("one");
objs.add("two");
printList(objs); // 编译错误
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
在上面的示例中,printList 方法接受一个 List 类型的参数,该参数的元素类型必须是 Integer
或 Integer
的超类。
因此我们可以将 List<Number>
类型和 List<Integer>
类型的对象传递给该方法,但不能将 List<Object>
类型的对象传递给该方法。
# extends
extend 关键字用于指定泛型类型参数的上界(upper bound),也就是指定泛型类型参数必须是某个特定类型的子类或者该特定类型本身。 使用 extend 时,泛型类型参数可以向下转型为其上界类型,这意味着你可以安全地将一个泛型类型参数赋值给其上界类型的变量。
例如:
public static void printList(List<? extends Number> list) {
for (Number elem : list) {
System.out.print(elem + " ");
}
System.out.println();
}
List<Integer> ints = new ArrayList<>();
ints.add(1);
ints.add(2);
printList(ints); // 输出: 1 2
List<Double> dbls = new ArrayList<>();
dbls.add(2.0);
dbls.add(3.0);
printList(dbls); // 输出: 2.0 3.0
List<String> strs = new ArrayList<>();
strs.add("one");
strs.add("two");
printList(strs); // 编译错误
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
在上面的示例中,printList 方法接受一个 List 类型的参数,该参数的元素类型必须是 Number
或 Number
的子类。
因此我们可以将 List<Integer>
类型和 List<Double>
类型的对象传递给该方法,但不能将 List<String>
类型的对象传递给该方法。
# 总结
super决定下界,extends决定上界,再举个简明例子:
有类 C 继承 B 继承 A 的继承链
对于:
List<? extends B> list1 = new ArrayList<A>(); //编译报错
List<? extends B> list2 = new ArrayList<B>();
List<? extends B> list3 = new ArrayList<C>();
1
2
3
2
3
因为 extends 决定上界,上界是B,那么只能接受BC
对于:
List<? super B> list4 = new ArrayList<A>();
List<? super B> list5 = new ArrayList<B>();
List<? super B> list6 = new ArrayList<C>(); //编译报错
1
2
3
2
3
因为 super 决定下界,下界是B,那么只能接受AB
编辑 (opens new window)
上次更新: 2023/05/28, 08:23:00