首页 > 技术文章 > 泛型与集合的注意事项

zhihaospace 2020-03-30 12:23 原文

一.List,List<Object>,List<?>三者区别

1.List

(1)List可以接受任意泛型赋值

List list = new ArrayList();
List list1 = new ArrayList<Object>();
List list2 = new ArrayList<Integer>();

(2)List可以赋值给任意类型

  • 注意遍历时可能会出现类型转换异常,这是由于list中可能存放不同类型数据导致转换不了

List list = new ArrayList();
list.add(111);
list.add(222);

List<Integer> list1 = list;

list1.forEach(System.out::println);
  • 将 list.add(222) 改为 list.add("222") 再执行就会出错
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
    at java.util.ArrayList.forEach(ArrayList.java:1249)
    at code.TestDemo.main(TestDemo.java:16)

2.List<Object>

(1)List<Object>可以接受List赋值

List list = new ArrayList();
List<Object> list2 = list;

(2)确定类型的集合是不可以相互赋值的

  • List<Object>不可以赋值给List<Integer>,同时List<Integer>也不可以赋值给List<Object>

3.List<?>

  • List<?>在接受了其他泛型赋值之后,可以删除和清除元素 list2.remove(0); , list2.clear(); 

  • List<?>在接受了其他泛型赋值之后,不可以添加元素 list2.add(1); 但可以添加null元素 list2.add(null); 

  • List<?>可以获取元素但必须使用Object来接收,需要修改内部数据需判断之后强制类型转换再修改

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);

List<?> list2 = list;
list2.remove(0);
list2.clear();
 1 List<?> list2 = new ArrayList<T>() {
 2             {
 3                 add(new T(1));
 4                 add(new T(2));
 5                 add(new T(3));
 6             }
 7         };
 8 
 9         list2.add(null);    //可以添加null元素
10         Object obj = list2.get(1);
11 
12         if (obj instanceof T) {    //强制类型装换后可以改变内部数据
13             T t = (T) obj;
14             System.out.println(t.i);
15             t.i = 3;
16         }
17 
18         obj = list2.get(1);
19         if (obj instanceof T) {
20             System.out.println(((T) obj).i);
21         }

二.<? extends T>和<? super T>

 1.<? extends T>

(1)只允许接受T类型或T类型的子类赋值

List<Integer> list1 = new ArrayList<>();
List<Number> list2 = new ArrayList<>();
List<? extends Number> list = list1;
list = list2;

(2)不能使用add方法添加新元素,只能添加null

  • 不能 list.add(1); 

List<Integer> list1 = new ArrayList<>();
list1.add(1);
list1.add(2);

List<? extends Number> list = list1;
list.add(null);

(3)取出元素只能使用T类型以及T类型的父类接收

List<Integer> list1 = new ArrayList<>();
list1.add(1);
list1.add(2);

List<? extends Number> list = list1;
Number number = list.get(0);
Object number1 = list.get(0);

2.<? super T>

(1) 只允许接受T类型或T类型的父类赋值

List<Integer> list1 = new ArrayList<>();
List<Number> list2 = new ArrayList<>();

List<? super Integer> list = list1;
list = list2;

(2)只能使用add方法添加T类型元素或T类型的子类型元素

List<Integer> list1 = new ArrayList<>();
List<? super Integer> list = list1;
list.add(new Integer(1));

(3)取出类型只能使用Object类型接收

List<Object> list1 = new ArrayList<>();
list1.add(new Animal());
list1.add(new Person());
list1.add(new Man());

List<? super Man> list = list1;
Object obj = list1.get(1);

三.注意事项

1.List<Parent> 与 List<Child>没有父子关系也不是同一个关系

1 List<Number> list = new ArrayList<Integer>(); //报错
 1 public static class MyList<T> {
 2     List<T> list = new ArrayList<>();
 3  
 4     // 把输入参数塞给自己,类似于生产操作
 5     public void pushList(List<T> t) {
 6         list.addAll(t);
 7     }
 8  
 9     // 把自己的内容塞给输入参数,类似于让输入参数做消费。
10     public void pollList(List<T> t) {
11          t.addAll(list);
12     }
13 }
1 MyList<Number> myList = new MyList<>();
2  
3 List<Integer> intList = new ArrayList<>();
4 myList.pushList(intList);   //报错,List<Number> 与List<Integer>毫无关系
5  
6 List<Object> objectList = new ArrayList<>();
7 myList.pollList(objectList);  //报错,List<Number> 与List<Object>毫无关系

 

推荐阅读