泛型与集合的注意事项
一.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>毫无关系