一、集合概述
集合:就是一个存储数据的容器。
集合与数组一样,也是一个容器,与数组的区别:
- 数组长度固定,集合的长度不固定
- 数组可以存储基本类型和引用类型,集合中存储的元素类型只能是引用类型(包装类存储级别数据类型)
集合框架图
二、泛型
2.1 概念
泛型就是可以表示一个广泛数据类型的类型参数(泛型只能表示引用类型),把数据类型作为参数来传递。
使用目的:约束能够保存的数据类型,保证数据类型一致化
2.2 参数类别
- 形式参数:声明方法时,在方法的参数列表中声明,而且在方法体中会使用到,是一个未知的数据
- 实际参数:调用方法时,实际传递的参数
- 类型参数:在一个类中声明一个未知的数据类型,在类中可以使用这个类型,但是具体类型取决于实例化时传入的实际类型(泛型)
2.3 泛型使用注意事项
- 泛型前后一致!!!
//前后的数据类型必须一致
ArrayList<String> strings = new ArrayList<String>();
ArrayList<String> strings = new ArrayList<>();
- 泛型不能在类中声明静态属性static、常量final
final修饰的属性必须在声明的同时初始化,所以泛型不能声明常量。
static修饰的属性是静态属性,先于对象的创建,而泛型类型取决于创建对象时传入的实际类型,所以泛型不能声明静态属性 - 泛型不能在类中初始化数组,但是可以声明数组
初始化数组时需要给元素进行分配空间,但是泛型类型不确定无法分配空间
- 在类中不能使用泛型声明参数个数相同的重载方法
当一个类中有两个泛型时,创建对象时,两个泛型使用相同类型替换,那么重载方法就是相同的方法
2.4 泛型应用范畴
成员方法泛型
注意事项
- 定义一个方法,能够接受任意数据类型,而且返回值和接受到的数据类型一致, 不需要强转
- 在【方法返回值】之前加入泛型标识符E K V T
类的泛型
注意事项
- 在【类名】之后加入泛型标识符E K V T
- 一个类声明时定义了自定义泛型,如果在【创建】该类对象时,确定了泛型的具体数据类型, 那么在类内的所有【非静态成员变量】和【成员方法】用到的数据类型就是创建时确定的数据类型
- 一个类声明时定义的自定义泛型,类内的【静态成员变量】和【静态成员方法】不能使用
- 如果一个类中声明了自定义泛型,创建对象时却没有给定自定义泛型对应的数据类型,那么类内所有用到自定义泛型的类型都会变成 Object
- 如果类内的静态方法,想要使用自定义泛型,那么就在方法上自己定义, 为了阅读性和方便理解这里推荐使用和类名定义时不同的泛型占位符,并在【static】关键字后面声明泛型
接口的泛型
注意事项
- 定义接口:在接口名后面加入泛型标识符E K V T
- 遵从接口分为两种方式:
自由:在【类名&&接口名】后面加入泛型标识符E K V T,由调用者决定数据类型
限制:【仅仅在接口名】后面加入【具体数据类型】,这样调用的时候不需要泛型格式书写
2.5 泛型的上下限
泛型上限
格式:
<? extends E>
<? extends Number>
/**
* ?为通配符,表示类型的范畴限定在了"E类型及其子类"
* Number为数值类型, 其子类包括Integer/Short/Long/Float/Double
*/
泛型的上限一般用于数据的存储
泛型下限
格式:
<? super E>
<? super Number>
/**
* ?为通配符,表示类型的范畴限定在了"E类型及其父类"
* Number父类是Object,所以传入对象只能是Number或者Object类
*/
泛型的下限一般用于读取数据, 用于一定的规则操作,如比较操作