10.1 泛型的引出
10.1.1 个人理解
- 集合中的添加的元素可以是任意类型,但某些特定需求下,需要将添加的类型限定在某一种类型,以保证开发效率、代码规范等目的。
- 这种情况下靠人为去控制添加的元素类型不具有显示意义,编译器也不会在编译程序的时候指出这种失误。
- 为了保证添加的元素类型一致、编译器能够在编译阶段(程序书写阶段)就发现错误、后续的代码中简化代码,java在JDK5.0时引入了泛型,它在集合、接口等有确定传入类型需求的类、接口声明时添加了占位元素,使得在使用时,用指定的元素类型替换占位元素,以达到上述目的。
10.1.2 官方理解
- 泛型又称参数化类型,用于解决数据类型的安全性问题
- 需要在类声明或实例化时指定具体类型。
- java泛型可以保证程序在编译时不出现警告,运行时也就不会产生ClassCastException,同时能够使diamagnetic更简洁、健壮。
- 泛型的作用是:可以在类声明时,通过一个标识,表示类中某个属性、某个方法的返回值、某个方法的参数是指定类型。
10.2 泛型的实例化
- 在创建对象时,
<>
中写上具体的参数类型。
- 例子:
List<String> list = new ArrayList<String>();
- 简写:
List<String> list = new ArrayList<>();
- 好处:由编译器去自动推断数据类型,进一步保证数据安全。
- 细节:
- 写入的数据类型只能是引用类型,传入基本数据类型会报错
- 可以写入声明时指定的类型,或指定类型的子类型
<>
内不传入时,默认的泛型是Object
10.3 自定义泛型
10.3.1 自定义泛型类
- 泛型的声明
class 类名<K, V>{}
- K、V、T都不表示具体值或具体的类型,而是一个占位标记符,可以是任意标识符。
- 一般E使用在集合中
- T使用在类中
- K表示键
- V表示值
- N表示数值类型
- ?表示不确定的java类型
<>
内可以写入多个,表示多个泛型
- 声明细节:
- 泛型可以是属性、方法参数、方法返回值、构造器参数
- 泛型是数组时,不能在声明时初始化。
- 数组在
new
时,不确定泛型类型就不能在内存中开辟空间
- 静态属性、静态方法(参数、返回值)不能是泛型
- 静态属性和静态方法随类的加载而加载,此时对象还没有创建,JVM无法初始化泛型
- 泛型的类型在创建对象时确定
- 如果没有指定类型,则默认为Object
10.3.2 自定义泛型接口
- 泛型的声明
interface 接口名<T>{}
- K、V、T都不表示具体值或具体的类型,而是一个占位标记符,可以是任意标识符。
- 一般E使用在集合中
- T使用在类中
- K表示键
- V表示值
- N表示数值类型
- ?表示不确定的java类型
<>
内可以写入多个,表示多个泛型
- 声明细节:
- 泛型可以是方法参数、方法返回值
- 不可以是属性,接口的属性是
public static final
- 静态方法(参数及返回值)不能是泛型
- 泛型的类型在继承接口或实现接口时确定
- 如果没有指定类型,则默认为Object,且实现类默认使用Object
- 继承接口时确定:子接口的实现类会自动使用子接口确定的类型
- 实现接口时确定:实现类会自动使用实现类确定的类型
10.3.3 自定义泛型方法
- 泛型的声明:
修饰符 <参数类型列表> 返回类型 方法名(参数列表){}
- 声明细节:
- 可以定义在普通类、普通接口中,也可以定义在泛型类、泛型接口中。
- 泛型方法被调用时类型会确定
public void eat(E e){}
修饰符后没有泛型标识,表示这个方法不是泛型方法,而是方法使用了(类声明的)泛型- 泛型方法可以使用类声明的泛型,也可以使用自己声明的泛型
10.4 泛型的继承和通配符
- 不对,泛型没有继承性
通配符注意点: