泛型通配符以及边界
# 泛型的通配符?和 T 的区别
T
可以用于声明变量或常量而?
不行T
一般用于声明泛型类或方法,通配符?
一般用于泛型方法的调用代码和形参T
在编译期会被擦除为限定类型或 0bject,通配符用于捕获具体类型。
# 什么是无界通配符
无界通配符可以接收任何泛型类型数据,用于实现不依赖于具体类型参数的简单方法,可以捕获参数类型并交由泛型方法进行处理。
public static void test1(List<?> list) {
// todo 业务处理
System.out.println(list.toString());
}
1
2
3
4
2
3
4
# List 和 List<?> 有何不同
List<?> list
表示 list
是持有某种特定类型的List,但是并不知道是具体那种类型,因此我们在往里添加元素的时候会报错。
List list
表示 list
中的元素是 Object 类型的,可以进行对象添加操作
如下
public static void main(String[] args) {
List list1 = new ArrayList<>();
List<?> list2 = new ArrayList<>();
list1.add("散装java");
// 下面这个报错
list2.add("散装java");
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 什么是有界通配符
我们在使用泛型的时候,可以限定泛型的上下边界,如下
// <? extends Number> 上界通配符
public static void test1(List<? extends Number> list) { }
// <? super Number> 下界通配符
public static void test2(List<? super Number> list) { }
1
2
3
4
2
3
4
<? extends Number>
上界通配符 要求 ?
必须是Number
的子类
<? super Number>
下界通配符 要求 ?
必须是Number
的父类
也就是说,上述例子中 test1
方法的参数,可以使 ArrayList<Integer>()
、ArrayList<Long>()
等等,但是不能是 ArrayList<String>()
;
而 test2
中,则可以是 ArrayList<Object>()
,而不能是 ArrayList<Integer>()
test1(new ArrayList<Integer>());
test1(new ArrayList<Long>());
// 下面的会报错
test1(new ArrayList<String>());
test2(new ArrayList<Object>());
// 下面的会报错
test2(new ArrayList<Long>());
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# <? extends xxx >和 <? super xxx> 有什么区别?
两者接收参数的范围不同。
并且,使用 <? extends xxx>
声明的泛型参数只能调用 get()
方法返 xxx
类型,调用 set()
报错。
使用 <? super xxx>
声明的泛型参数只能调用 set()
方法接收 xxx
类型,调用 get()
报错。
List<? extends Number> list = new ArrayList<>();
// 这里因为 ? 可能是Number的任何一个子类,所以,你在往里添加数据的时候,它并不能确定
// 因此会抛出异常 ,提示:capture of ? extends Number
list.add(new Double(1));
// 而获取则一定是 Number 的子类, 所以可以用父类来接收
final Number number = list.get(0);
List<? super Number> list2 = new ArrayList<>();
// 这里因为 ? 是 Number 的 父类 ,所以不管你往里面添加什么的数字,一定属于 Number 的子类
list2.add(1);
// 而在获取这个数据的时候, 你并不能确定你拿到的数据是什么。因为 ? 是 Number 的父类
final Number object = list2.get(0);
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# <? extends xxx> 和 < T extends xxx> 有什么区别
< T extends xxx>
用于定义泛型类和方法,擦除后为xxx
类型
<? extends xxx>
用于声明方法的形参,接收xxx
和其子类型
上次更新: 2022/11/28, 19:59:06