学习目标
能够说出集合与数组的区别
数组:
1.是引用数据类型的一种
2.可以存储多个元素
3.数组的长度是固定的 int[] arr1 = new int[10]; int[] arr2 = {1,2,3};
4.数组即可以存储基本类型的数据,又可以存储引用数据类型的数据
int[],double[],String[],Student[]
集合:
1.是引用数据类型的一种
2.可以存储多个元素
3.集合的长度是可以变化的(可以往集合中添加元素,删除集合中的元素)
4.只能存储引用数据类型的数据
ArrayList<int> 错误 ArrayList<Integer> ArrayList<Student>
能够使用Collection集合的常用功能(重点)
public boolean add(E e) : 把给定的对象添加到当前集合中 。
public boolean remove(E e) : 把给定的对象在当前集合中删除。
public boolean contains(Object obj) : 判断当前集合中是否包含给定的对象。
public boolean isEmpty() : 判断当前集合是否为空。
public int size() : 返回集合中元素的个数。
public Object[] toArray() : 把集合中的元素,存储到数组中
public void clear() :清空集合中所有的元素。
能够使用迭代器对集合进行取元素(重点)
//1.创建集合对象,往集合中添加元素
Collection<String> coll = new ArrayList<>();
//Collection<String> coll = new HashSet<>();
coll.add("詹姆斯");
coll.add("姚明");
coll.add("科比");
coll.add("乔丹");
coll.add("艾弗森");
//2.使用Collection接口中的方法iterator,获取迭代器的实现类对象
Iterator<String> it = coll.iterator();
//3.使用迭代器对象Iterator中的方法hasNext和next遍历集合
while(it.hasNext()){
String s = it.next();
System.out.println(s);
}
能够使用增强for循环遍历集合和数组(重点)
for(集合|数组中元素的数据类型 变量名: 集合|数组){
sout(变量名);
}
int[] arr = {1,2,3};
for(int i : arr){
sout(i);
}
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
for(String s : list){
sout(s);
}
能够理解泛型上下限
泛型的上限限定: ? extends E ==>传递的未知类型?只能是E的子类或者本身
泛型的下限限定: ? super E ==>传递的未知类型?只能是E的父类或者本身
能够阐述泛型通配符的作用
泛型的通配符: ? 可以接收任意的数据类型
能够说出常见的数据结构
栈,队列,数组,链表,红黑树
能够说出数组结构特点
查询快,增删慢
能够说出栈结构特点
先进后出
能够说出队列结构特点
先进先出
能够说出单向链表结构特点
查询慢,增删快
第一章 Collection集合
1.集合和数组的区别
数组:
1.是引用数据类型的一种
2.可以存储多个元素
3.数组的长度是固定的 int[] arr1 = new int[10]; int[] arr2 = {1,2,3};
4.数组即可以存储基本数据类型的数据,又可以存储引用数据类型的数据 int[] double[] String[] Student[]
集合:
1.是引用数据类型的一种
2.可以存储多个元素
3.集合的长度是可以变化的(添加元素,删除集合中的元素)
4.集合只能存储引用数据类型的数据
ArrayList<int> 错误 ArrayList<Integer> ArrayList<Student> ArrayList<String>正确
2.集合常用类的继承体系
3.Collection常用功能(重点)
package com.itheima.demo01Collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
/*
java.util.Collection<E>
Collection 层次结构 中的根接口。
Collection 表示一组对象,这些对象也称为 collection 的元素。
一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。
Collection接口中定义了所有单列集合共性的成员方法,所有的实现类都可以使用
public boolean add(E e) : 往集合中添加元素
public boolean remove(E e) : 移除集合中指定的元素
public boolean contains(Object obj) : 判断当前集合中是否包指定的元素。
public boolean isEmpty() : 判断当前集合是否为空。
public int size() : 返回集合中元素的个数。获取集合的长度
public Object[] toArray() : 把集合中的元素,存储到数组中
public void clear() :清空集合中所有的元素。
*/
public class Demo01Collection {
public static void main(String[] args) {
//创建Collection集合对象:多态(接口指向实现类对象,扩展性强)
Collection<String> coll = new ArrayList<>();
coll = new HashSet<>();
/*
public boolean add(E e) : 往集合中添加元素
返回值:boolean
添加成功,返回true,添加元素百分之百会成功
添加失败,返回false
*/
boolean b1 = coll.add("张三");
System.out.println("b1:"+b1);//b1:true
coll.add("李四");
coll.add("王五");
coll.add("张三");
coll.add("赵六");
coll.add("田七");
System.out.println(coll);//[张三, 李四, 王五, 张三, 赵六, 田七] 打印对象名,不是地址值,重写了Object类的toString方法
/*
public boolean remove(E e) : 移除集合中指定的元素
返回值:boolean
集合中存储指定的元素,移除元素,返回true;如果集合移除的元素有相同的,只会移除第一个
集合中不存在指定的元素,remove方法对集合没有影响,返回false
*/
boolean b2 = coll.remove("张三");
System.out.println("b2:"+b2);//b2:true
System.out.println(coll);//[李四, 王五, 张三, 赵六, 田七]
boolean b3 = coll.remove("赵四");
System.out.println("b3:"+b3);//b3:false
System.out.println(coll);//[李四, 王五, 张三, 赵六, 田七]
/*
public boolean contains(Object obj) : 判断当前集合中是否包指定的元素。
返回值:boolean
集合中包含指定的元素,返回true
集合中不包含指定的元素,返回false
*/
boolean b4 = coll.contains("田七");
System.out.println("b4:"+b4);//b4:true
boolean b5 = coll.contains("胡歌");
System.out.println("b5:"+b5);//b5:false
/*
public boolean isEmpty() : 判断当前集合是否为空。
返回值:boolean
集合中没有元素,是空的,返回true
集合中有元素,不是空的,返回false
*/
boolean b6 = coll.isEmpty();
System.out.println("b6:"+b6);//b6:false
/*
public int size() : 返回集合中元素的个数。获取集合的长度
*/
int size = coll.size();
System.out.println("size:"+size);//size:5
/*
public Object[] toArray() : 把集合中的元素,存储到数组中
*/
Object[] arr = coll.toArray();
System.out.println(Arrays.toString(arr));//[李四, 王五, 张三, 赵六, 田七]
/*
public void clear() :清空集合中所有的元素。
注意:
此方法只是清空集合中的元素,不是删除集合;清空完集合还存在,还可以使用
*/
coll.clear();
System.out.println(coll);//[]
System.out.println(coll.size());//0
System.out.println(coll.isEmpty());//true
}
}
第二章 Iterator迭代器
1.迭代器的概述
/*
迭代器:是一种通用取出集合中元素的方式
迭代器的由来:
集合有很多种,每种集合的数据结构不同(数组,链表,哈希表...),集合取出元素的方式也不同
我们不可能为每种集合都定义一种取出元素的方式,浪费
所以我们可以使用迭代器,是集合通用的取出元素的方式
迭代器的原理:
判断集合中还有没有元素,有就取出来;
再判断集合中还有没有元素,有再取出来;
一直判断到集合中没有元素为止,这种取出元素的方式叫迭代
------------------------------------------------------------------------------------
java.util.Iterator<E>接口:对 collection 进行迭代的迭代器。
Iterator接口的常用方法:
boolean hasNext() 如果仍有元素可以迭代,则返回 true。
判断集合中还没有没有元素;有返回true,没有返回false
E next() 返回迭代的下一个元素。 取出集合中的元素
------------------------------------------------------------------------------------
Iterator是一个接口无法创建对象使用,使用Iterator接口的实现类对象,Iterator接口的实现类对象是每个集合的内部类(了解)
我们可以使用Collection接口中的方法iterator获取迭代器Iterator接口的实现类对象
Iterator<E> iterator() 返回在此 collection 的元素上进行迭代的迭代器。
注意:
我们无需关注iterator方法返回的是接口的哪个实现类对象,我们只需要会使用Iterator接口来接收这个实现类对象即可(多态)
*/
2.迭代器的基本使用(重点)
/*
迭代器的使用步骤(重点):
1.创建集合对象,往集合中存储元素
2.使用Collection接口中的方法iterator,获取迭代器接口的实现类对象
3.使用迭代器对象Iterator接口中的方法hasNext和next遍历集合
*/
public class Demo01Iterator {
public static void main(String[] args) {
//1.创建集合对象,往集合中存储元素
Collection<String> coll = new ArrayList<>();
coll.add("詹姆斯");
coll.add("姚明");
coll.add("科比");
coll.add("乔丹");
coll.add("艾弗森");
/*
2.使用Collection接口中的方法iterator,获取迭代器接口的实现类对象
注意:迭代器Iterator是有泛型的,迭代的泛型跟着集合走,集合是什么泛型,迭代器就是什么泛型
*/
//多态 接口 = 实现类对象
Iterator<String> it = coll.iterator();
//3.使用迭代器对象Iterator接口中的方法hasNext和next遍历集合
/*
我们发现使用迭代器取出元素是一个重复的过程,所以我们可以使用循环优化代码
不知道集合中有多个元素,一般使用while循环
while循环结束的条件:it.hasNext方法返回false
*/
while (it.hasNext()){//判断集合中还有没有元素
//有元素,取出元素
String s = it.next();
System.out.println(s);
}
System.out.println("-----------------------------");
//注意:迭代器只能使用一次,想要在遍历元素,必须重新获取一个新的迭代器
for(Iterator<String> it2 = coll.iterator();it2.hasNext();){
String s = it2.next();
System.out.println(s);
}
/*boolean b = it.hasNext();
System.out.println(b);//true
String s = it.next();
System.out.println(s);//詹姆斯
b = it.hasNext();
System.out.println(b);//true
s = it.next();
System.out.println(s);//姚明
b = it.hasNext();
System.out.println(b);//true
s = it.next();
System.out.println(s);//科比
b = it.hasNext();
System.out.println(b);//true
s = it.next();
System.out.println(s);//乔丹
b = it.hasNext();
System.out.println(b);//true
s = it.next();
System.out.println(s);//艾弗森
b = it.hasNext();
System.out.println(b);//false*/
//s = it.next();//没有元素,就不能使用next方法获取元素,在获取元素会抛出没有元素异常:NoSuchElementException
}
}
3.迭代器的执行原理
4.迭代器的并发修改异常(面试)
package com.itheima.demo02Iterator;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
/*
迭代器的并发修改异常:在使用迭代器遍历集合的过程中,对集合长度进行了修改,迭代器就会抛出并发修改异常
ConcurrentModificationException
注意:
1.并发:遍历和修改同时进行
2.修改:修改集合的长度(添加元素,删除元素)
解决方案:
1.遍历集合的同时,不修改集合的长度
2.Iterator接口有一个子接口叫ListIterator
在ListIterator接口定义了往集合中添加元素的方法
public interface ListIterator<E>extends Iterator<E>
void add(E e) 迭代器中往集合添加元素的方法
void remove() 删除的是next方法取出的元素
注意:
1.如果使用迭代器中的add|remove方法,往集合中添加|删除元素
就相当于集合和迭代器商量好了,可以往集合中添加|删除元素,迭代器就不会抛出并发修改异常了
2.ListIterator迭代器只能遍历List接口下的集合(ArrayList,LinkedList),不能遍历Set接口下的集合(HashSet,LinkedHashSet)
*/
public class Demo02Iterator {
public static void main(String[] args) {
//创建集合对象,往集合中添加元素
ArrayList<String> list = new ArrayList<>();
list.add("aaa");
list.add(null);
list.add("bbb");
list.add("ccc");
list.add("ddd");
list.add("eee");
//使用迭代器遍历list集合
//使用集合中的方法iterator获取迭代器接口的实现类对象
Iterator<String> it = list.iterator();
//使用Iterator迭代器中的方法hasNext和next遍历集合
while (it.hasNext()){
String s = it.next();
System.out.println(s);
/*
需求:增加一个判断,如果取出的元素是"ccc"
就给集合添加一个新的元素"itcast"
编程技巧:使用equals方法判断的时候,一般都把已知的值写在前边,防止空指针异常
*/
if("ccc".equals(s)){
//list.add("itcast");//ConcurrentModificationException
//list.remove("ddd");//ConcurrentModificationException
}
}
System.out.println("--------------第二种解决并发修改异常的方法------------------------");
//使用List接口中的方法listIterator获取ListIterator迭代器接口的实现类对象
//ListIterator<E> listIterator() 返回此列表元素的列表迭代器(按适当顺序)。
ListIterator<String> lit = list.listIterator();
//使用迭代器中的方法hasNext和next遍历集合
while (lit.hasNext()){
String s = lit.next();
System.out.println(s);
/*
需求:增加一个判断,如果取出的元素是"ccc"
就给集合添加一个新的元素"itcast"
*/
if("ccc".equals(s)){
//lit.add("itcast");//使用迭代器中的add方法,往集合中添加元素
lit.remove();//删除的是next方法取出的元素
}
}
//遍历的过程中是不会打印出新添加的元素的,遍历之后在打印就可以看到了
System.out.println(list);//[aaa, null, bbb, ccc, itcast, ddd, eee] [aaa, null, bbb, ddd, eee]
}
}
5.迭代器的实现类是每个集合的内部类(了解)
6.增强for循环(重点)
注意:
增强for循环底层是一个迭代器,所以在使用增强for循环遍历的时候,不能对集合的长度进行修改,否则会抛出并发修改异常
package com.itheima.demo02Iterator;
import java.util.ArrayList;
/*
增强for循环(重点)
是JDK1.5之后出现的新特性
使用for循环的方式,对迭代器进行了简化
增强for循环内部就是一个迭代器,对迭代器进行了封装
Collection接口有一个父接口叫Iterable
public interface Collection<E> extends Iterable<E>
java.lang.Iterable<T>接口
实现这个接口允许对象成为 "foreach" 语句的目标。
Collection接口继承了Iterable接口,所以可以使用增强for循环
Collection接口所有的实现类,都可以使用增强for循环(ArrayList,LinkedList,HashSet...)
------------------------------------------------------------
增强for循环的格式:重点
for(集合|数组中元素的类型 变量名 : 集合名|数组名){
sout(变量名);
}
*/
public class Demo03Foreach {
public static void main(String[] args) {
show03();
}
/*
使用增强for循环遍历集合
快捷键:
数组名|集合名.for 增强for
*/
private static void show03() {
ArrayList<Student> list = new ArrayList<>();
list.add(new Student("张三",18));
list.add(new Student("李四",19));
list.add(new Student("王五",20));
for (Student s : list) {
//注意:增强for循环底层就是一个迭代器,在遍历的过程中不能修改集合的长度
//list.add(new Student("赵六",18));//ConcurrentModificationException
System.out.println(s);
}
}
/*
使用增强for循环遍历集合
好处:
可以在遍历的过程中使用元素特有的方法
*/
private static void show02() {
ArrayList<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbbbbbb");
list.add("cc");
list.add("ddddd");
for(String s : list){
System.out.println(s+"-->"+s.length());
}
}
/*
使用增强for循环遍历数组
好处:
格式简单
弊端:
只能遍历,不能修改数组中的元素
*/
private static void show01() {
int[] arr1 = {1,2,3};
//使用普通for循环遍历数组
for (int i = 0; i < arr1.length; i++) {
arr1[i]*=2;
System.out.println(arr1[i]);
}
System.out.println("arr1[0]:"+arr1[0]);
System.out.println("--------------------");
int[] arr2 = {1,2,3};
for(int s : arr2){
s *= 2;
System.out.println(s);
}
System.out.println("arr2[0]:"+arr2[0]);
}
}
第三章 泛型
1.泛型的概述
2.使用泛型的好处
package com.itheima.demo03Generic;
import java.util.ArrayList;
import java.util.Iterator;
/*
java中的泛型:是一个伪泛型,在.java文件中有,但是.class文件中没有
*/
public class Demo01Generic {
public static void main(String[] args) {
show02();
}
/*
使用泛型创建ArrayList集合对象
好处:
1.使用什么泛型就只能存储什么类型的数据;避免向下转型抛出类型转换异常
2.写上泛型存储的是什么类型,取出的就是什么类型,不用向下转型,就可以使用特有的方法
弊端:
1.不能什么类型的数据都存储
*/
private static void show02() {
ArrayList<String> list = new ArrayList<>();
list.add("aaa");
//list.add(1);
//使用迭代器遍历list集合
Iterator<String> it = list.iterator();
while (it.hasNext()){
String s = it.next();
System.out.println(s+"-->"+s.length());
}
}
/*
不使用泛型创建ArrayList集合对象
好处:
不使用泛型,集合默认的数据类型就是Object类型,可以存储任意数据类型的元素
弊端:
1.不能使用元素特有的方法(多态)
2.在进行向下转型的时候,容易引发类型转换异常
*/
private static void show01() {
ArrayList list = new ArrayList();
list.add("aaa");
list.add(1);
//使用迭代器遍历list集合
Iterator it = list.iterator();
while (it.hasNext()){
//存储的泛型是Object类型,取出元素类型也是Object类型
Object obj = it.next();
System.out.println(obj);
/*
多态 Object obj = "aaa"; 无法使用子类特有的方法
*/
if(obj instanceof String){
String s = (String)obj;
System.out.println(s.length());
}
}
}
}
通过反编译软件,查看的class文件中,没有泛型
3.定义和使用含有泛型的类
package com.itheima.demo04GenericClass;
/*
定义和使用含有泛型的类:模拟ArrayList集合
当我们不知道使用什么类型的时候,就可以使用泛型,是一个未知的数据类型
可以给泛型赋值任意的数据类型:Integer,Student,Person,String...
定义格式:
public class 类名<泛型>{
类中使用数据类型的地方,都可以使用类上定义好的泛型
}
什么时候确定类上泛型的数据类型
创建对象的时候,确定类上泛型的数据类型;对象使用什么类型,类的泛型就是什么类型
*/
public class GenericClass<C> {
private C name;
public C getName() {
return name;
}
public void setName(C name) {
this.name = name;
}
}
package com.itheima.demo04GenericClass;
public class Demo01GenericClass {
public static void main(String[] args) {
//创建GenericClass对象,不使用泛型,类型默认就是Object类型
GenericClass gc1 = new GenericClass();
//创建GenericClass对象,泛型使用String类型
GenericClass<String> gc2 = new GenericClass<>();
gc2.setName("aaa");
String name = gc2.getName();
System.out.println(name);
//创建GenericClass对象,泛型使用Integer类型
GenericClass<Integer> gc3 = new GenericClass<>();
gc3.setName(10);
Integer in = gc3.getName();
System.out.println(in);
}
}
4.定义和使用含有泛型的方法(重点)
package com.itheima.demo05GenericMethod;
/*
定义和使用含有泛型的方法(重点)
泛型需要定义在方法的修饰符和返回值类型之间
定义格式:
修饰符 <泛型> 返回值类型 方法名(参数类型-->使用泛型){
方法体;
}
什么时候确定泛型的数据类型:
调用方法,传递的参数是什么类型,方法的泛型就是什么类型
*/
public class GenericMethod {
//定义含有泛型的方法(重点)
public <M> void method01(M m){
System.out.println(m);
}
//定义含有泛型的静态方法(了解)
public static <S> void method02(S s){
System.out.println(s);
}
//定义含有泛型的方法,返回值类型使用泛型(了解==>看源码)
public <AAA> AAA method03(AAA aaa){
System.out.println(aaa);
return aaa;
}
}
package com.itheima.demo05GenericMethod;
import com.itheima.demo02Iterator.Student;
public class Demo01GenericMethod {
public static void main(String[] args) {
//创建GenericMethod对象
GenericMethod gm = new GenericMethod();
gm.method01(1);
gm.method01("aaa");
gm.method01(1.1);
gm.method01(true);
gm.method01('@');
gm.method01(new Student("徐峥",45));
System.out.println("------------------------------");
//通过类名.方法名(参数)可以直接调用静态方法
GenericMethod.method02(1);
GenericMethod.method02("aaa");
GenericMethod.method02(1.1);
System.out.println("------------------------------");
Integer in = gm.method03(11);
System.out.println(in);
String abc = gm.method03("abc");
System.out.println(abc);
}
}
5.定义和使用含有泛型的接口
package com.itheima.demo06GenericInterface;
/*
定义含有泛型的接口
*/
public interface GenericInterface<I> {
//定义抽象方法,使用接口上的泛型,作为参数的类型
public abstract void show(I i);
}
package com.itheima.demo06GenericInterface;
/*
含有泛型的接口:第一种使用方式
定义一个类,实现含有泛型的接口,在实现接口的同时,指定接口泛型的数据类型
格式:
public class GenericInterfaceImpl1 implements GenericInterface<String>{
重写接口中的方法,使用指定的类型String
public void show(String s) { }
}
public class GenericInterfaceImpl1 implements GenericInterface<Integer>{
重写接口中的方法,使用指定的类型Integer
public void show(Integer integer) { }
}
*/
public class GenericInterfaceImpl1 implements GenericInterface<Integer>{
@Override
public void show(Integer in) {
System.out.println(in);
}
}
package com.itheima.demo06GenericInterface;
/*
含有泛型的接口:第二种使用方式
定义类实现含有泛型的接口,接口使用什么泛型,实现类就使用什么泛型
实现类跟着接口走,就和定义一个含有泛型的类是一样的
格式:
public class GenericInterfaceImpl2<I> implements GenericInterface<I>{
重写的方法使用接口上的泛型
public void show(I i) { }
}
注意:
创建对象的时候,确定泛型的数据类型;创建对象是什么数据类型,泛型就是什么数据类型
*/
public class GenericInterfaceImpl2<I> implements GenericInterface<I>{
@Override
public void show(I i) {
System.out.println(i);
}
}
package com.itheima.demo06GenericInterface;
public class Demo01GenericInterface {
public static void main(String[] args) {
//创建GenericInterfaceImp1对象
GenericInterfaceImpl1 gii1 = new GenericInterfaceImpl1();
gii1.show(10);
//创建GenericInterfaceImpl2对象
GenericInterfaceImpl2<String> gii2 = new GenericInterfaceImpl2<>();
gii2.show("aaa");
GenericInterfaceImpl2<Double> gii3 = new GenericInterfaceImpl2<>();
gii3.show(1.1);
//匿名内部类
new GenericInterface<String>(){
@Override
public void show(String s) {
System.out.println(s);
}
}.show("123123");
}
}
6.泛型的通配符
package com.itheima.demo07Generic;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
/*
泛型的通配符
?:代表可以接收任意的数据类型
?已经由java定义好了,我们可以直接使用
*/
public class Demo01Generic {
public static void main(String[] args) {
Collection<Integer> c1 = new ArrayList<>();
c1.add(1);
c1.add(2);
Collection<String> c2 = new ArrayList<>();
c2.add("aaa");
c2.add("bbb");
printCollction(c1);
printCollction(c2);
/*
泛型的通配符只能作为方法参数的数据类型使用,不能创建对象作为数据类型使用
*/
//ArrayList<?> list = new ArrayList<>();
//list.add(1);
//list.add("a");
}
/*
定义一个方法,能遍历任意数据类型的Collection集合
1.Collection c:不写泛型,默认就是Object类型
2.可以使用泛型的通配符?,可以接收任意的数据类型
*/
public static void printCollction(Collection<?> c){
//使用迭代器遍历集合;集合的泛型是?,迭代器也是?
Iterator<?> it = c.iterator();
while (it.hasNext()){
/*
it.next方法取出的元素是什么类型
是Object类型,Object可以接收任意数据类型的数据
*/
Object obj = it.next();
System.out.println(obj);
}
}
}
package com.itheima.demo07Generic;
import java.util.ArrayList;
import java.util.Collection;
/*
泛型通配符的高级使用
泛型的通配符: ? 代表可以接收任意数据类型的数据
泛型的上限限定: ? extends E==>传递的未知类型?只能使用E的子类或者是E本身
泛型的下限限定: ? super E==>传递的未知类型?只能使用E的父类或者是E本身
*/
public class Demo02Generic {
public static void main(String[] args) {
Collection<Integer> list1 = new ArrayList<Integer>();
Collection<String> list2 = new ArrayList<String>();
Collection<Number> list3 = new ArrayList<Number>();
Collection<Object> list4 = new ArrayList<Object>();
/*
Integer extends Number extends Object
String exntends Object
*/
getElement1(list1);
//getElement1(list2);//报错 String和Number没有关系
getElement1(list3);
//getElement1(list4);//报错 Object类型是Number的父类,需要Number子类
//getElement2(list1);//报错 Integer是Number的子类,需要Number的父类
//getElement2(list2);//报错 String和Number没有关系
getElement2(list3);
getElement2(list4);
System.out.println("----------------------------------");
//Collection集合中的方法 boolean addAll(Collection<? extends E> c);
ArrayList<Integer> list01 = new ArrayList<>();
list01.add(1);
list01.add(2);
ArrayList<Object> list02 = new ArrayList<>();
//addAll的限制,传递list01集合泛型只能使用list02集合泛型的子类或者本身
list02.addAll(list01);//把list01集合中的所有元素都存储到list02中
System.out.println(list02);//[1, 2]
ArrayList<String> list03 = new ArrayList<>();
//list03.addAll(list01);
}
// 泛型的上限:此时的泛型?,必须是Number类型或者Number类型的子类
public static void getElement1(Collection<? extends Number> coll){}
// 泛型的下限:此时的泛型?,必须是Number类型或者Number类型的父类
public static void getElement2(Collection<? super Number> coll){}
}