片段1:
1 public void printCollection(Collection c) {
2 Iterator i = c.iterator();
3 for (int k = 0; k < c.size(); k++) {
4 System.out.println(i.next());
5 }
6 }
片段2:
1 public void printCollection(Collection<Object> c) {
2 for (Object e : c) {
3 System.out.println(e);
4 }
5 }
如果B是A的一个子类型(子类或者子接口),而G是具有泛型声明的类或接口, G<B>并不是G<A>的子类型!
比如: String是Object的子类,但是List<String >并不是List<Object>的子类。
但是:如果类 A 是类 B的父类,A<G> 是 B<G> 的父类。
实验一:
1 @Test
2 public void test(){
3
4 Object obj = null;
5 String str = null;
6 obj = str;
7
8 Object[] arr1 = null;
9 String[] arr2 = null;
10 arr1 = arr2;
11
12
13 //编译不通过
14 //Date date = new Date();
15 //str = date;
16
17
18 List<Object> list1 = null;
19 List<String> list2 = new ArrayList<String>();
20 //此时的list1和list2的类型不具有子父类关系
21 //编译不通过
22 //list1 = list2;
23
24 }
实验二:
1 public void testGenericAndSubClass() {
2 Person[] persons = null;
3 Man[] mans = null;
4 // 而 Person[] 是 Man[] 的父类.
5 persons = mans;
6
7 Person p = mans[0];
8
9
10 // 在泛型的集合上
11 List<Person> personList = null;
12 List<Man> manList = null;
13 // personList = manList;(报错)
14 }
实验三:
1 public void test(){
2
3 AbstractList<String> list1 = null;
4 List<String> list2 = null;
5 ArrayList<String> list3 = null;
6
7 list1 = list3;
8 list2 = list3;
9
10 List<String> list4 = new ArrayList<>();
11
12 }
(1)使用类型 通配符:?
比如: List<?> , Map<?,?>
List<?>是List<String>、 List<Object>等各种泛型List的父类。
(2)读取 List<?> 的对象 list 中的元素时,永远是安全的,因为不管 list 的真实类型是什么,它包含的都是Object。
(3)写入 List中的元素时,不行。因为我们不知道 c 的元素类型,我们不能向其中添加对象。
注意:唯一的例外是可以写入null,它是所有类型的成员。
1 @Test
2 public void test() {
3 List<Object> list1 = null;
4 List<String> list2 = null;
5
6 List<?> list = null;
7
8 list = list1;
9 list = list2;
10
11 //编译通过
12 //print(list1);
13 //print(list2);
14
15
16 }
17
18 public void print(List<?> list){
19 Iterator<?> iterator = list.iterator();
20 while(iterator.hasNext()){
21 Object obj = iterator.next();
22 System.out.println(obj);
23 }
24 }
List<?> 作为 List<String> 和List<Object> 的父类。
(1)将任意元素加入到其中不是类型安全的:
Collection<?> c = new ArrayList<String>();
c.add(new Object()); // 编译时错误
因为我们不知道c的元素类型,我们不能向其中添加对象。 add方法有类型参数E作为集合的元素类型。
我们传给add的任何参数都必须是一个未知类型的子类。因为我们不知道那是什么类型,所以我们无法传任何东西进去。
(2)唯一的例外的是null,它是所有类型的成员。
(3)另一方面,我们可以调用get()方法并使用其返回值。返回值是一个未知的类型,但是我们知道,它总是一个Object。
1 public static void main(String[] args) {
2 List<?> list = null;
3 list = new ArrayList<String>();
4 list = new ArrayList<Double>();
5 // list.add(3);//编译不通过
6 list.add(null);
7
8
9 List<String> l1 = new ArrayList<String>();
10 List<Integer> l2 = new ArrayList<Integer>();
11 l1.add("Hello World");
12 l2.add(15);
13 read(l1);
14 read(l2);
15 }
16 public static void read(List<?> list) {
17 for (Object o : list) {
18 System.out.println(o);
19 }
20 }
添加(写入):对于List<?>就不能向其内部添加数据。除了添加null之外。
获取(读取):允许读取数据,读取的数据类型为Object。
(1)编译错误:不能用在泛型方法声明上,返回值类型前面<>不能使用?
public static <?> void test(ArrayList<?> list){}
(2)编译错误:不能用在泛型类的声明上
class GenericTypeClass<?>{}
(3)编译错误:不能用在创建对象上,右边属于创建集合对象
ArrayList<?> list2 = new ArrayList<?>();
原文:https://www.cnblogs.com/niujifei/p/14801482.html