本帖最后由 琥珀88 于 2018-7-26 15:04 编辑
泛型通配符
1.基本概念
1.1无边界泛型通配符:就是<?>,比如List<?>.主要作用就是让泛型能够接收未知类型的数据。
1.2固定上边界泛型通配符:格式<? extends E>,E就是该泛型的上边界,用extends关键字不仅表示继承了父类E的子类,也代这实现了接口E的实 现类。主要作用是让泛型能够接收指定类及其子类类型的数据。
1.3固定下边界泛型通配符:格式<? super E>,E就是该泛型的下边界。主要作用是让泛型能够接收指定类及其父类类型的数据。
注意:1.运用泛型通配符主要是用来接收数据的,不能用来存储数据。
2.可以为一个泛型指定上边界或者下边界,但是不能同时指定上下边界。
2.基本使用方法
2.1无边界泛型通配符的使用,以List集合为例:
[Java] 纯文本查看 复制代码 import java.util.ArrayList;
import java.util.List;
public class Test {
public static void printList(List<?> list) {
for (Object o : list) {
System.out.println(o);
}
}
public static void main(String[] args) {
List<String> l1 = new ArrayList<>();
l1.add("aa");
l1.add("bb");
l1.add("cc");
printList(l1);
List<Integer> l2 = new ArrayList<>();
l2.add(11);
l2.add(22);
l2.add(33);
printList(l2);
}
} 其实使用List<?>的方式就是父类引用指向子类对象。但是printList方法不能写成
public static void printList(List<Object> list)的形式,因为Object虽然是所有类的父类,但是List<Object>跟其它泛型的List(比如List<String>、List<Number>)不存在继承关系。
List<?> 不能使用add方法(null除外),也不能使用get方法(Object除外)。因为不确定该List的类型,所以不知道add什么类型的数据,但是null是所有引用数据类型都具有的元素;get也一样因为不知道传入的List是什么类型,所以没办法接收得到的get,但是Object是所有数据类型和的父类,所以只有Object可以接收(父类引用指向子类对象)。
2.2固定上边界泛型通配符的使用,以List为例:
[Java] 纯文本查看 复制代码 import java.util.Arrays;
import java.util.List;
public class Test {
public static double sumOfList(List<? extends Number> list) {
double s = 0.0;
for (Number n : list) {
// 注意这里得到的n是其上边界类型的, 也就是Number, 需要将其转换为double.
s += n.doubleValue();
}
return s;
}
public static void main(String[] args) {
List<Integer> list1 = Arrays.asList(1, 2, 3, 4);
System.out.println(sumOfList(list1));
List<Double> list2 = Arrays.asList(1.1, 2.2, 3.3, 4.4);
System.out.println(sumOfList(list2));
}
}
List<? extends E>不能使用add方法。因为泛型<? extends E>指的是E及其子类,如果E有多个子类,那么在传入的时候就不知道到底是什么类。
对于get方法,可以使用E 类型接收(父类引用指向子类对象)。
2.3固定下边界泛型通配符的使用,以List为例:
[Java] 纯文本查看 复制代码 import java.util.ArrayList;
import java.util.List;
public class Test {
public static void addNumbers(List<? super Integer> list) {
for (int i = 1; i <= 10; i++) {
list.add(i);
}
}
public static void main(String[] args) {
List<Object> list1 = new ArrayList<>();
addNumbers(list1);
System.out.println(list1);
List<Number> list2 = new ArrayList<>();
addNumbers(list2);
System.out.println(list2);
List<Double> list3 = new ArrayList<>();
// addNumbers(list3); // 编译报错
}
}
List<? super E>能调用add方法,因为在addNumbers方法中add的元素就是Integer类型,而传入的list不管是什么类型,都是Integer或者Integer父类类型。
不能抵用get方法,原因是传入的类都是Integer或其父类类型,传入的数据类型可能是Integer到Object之间的任何类型,不知道是什么具体类型,所以没办法接收,只能是Object,因为所有类都是Object的子类
|