目录
1. 基本介绍
1.1 传统方法的缺点
(1)在不使用泛型,使用前面学过的知识,将元素添加到集合中时,不能对加入到集合中的数据类型进行约束,是不安全的。
(2)按照前面学过的知识,添加的元素是创建的对象时,对该集合进行遍历,需要进行类型转换(向下转型),如果集合数据量较大,会影响效率。
1.2 泛型的优点
(1)编译时,程序会检查添加元素的类型,提高了安全性。
(2)添加的元素是创建的对象时,可以直接取出对应的数据类型进行遍历,不需要进行类型转换,提高了效率。
(3)不再提示编译警告。
1.3 泛型基本介绍
(1)泛型可以理解为,表示数据类型的一种数据类型。可以表示多种数据类型(如:Integer、String、Dog等),具体表示的数据类型由程序员来决定。
(2)泛型又称参数化类型,是JDK 5.0出现的新特性,解决数据类型的安全性问题。
(3)在类声明或实例化时,只要指定需要的具体类型即可。
例:ArrayList类的底层定义是public class ArrayList<E> { },E被称为泛型。而我们在创建ArrayList类对象时,传入的Dog类型,是将Dog赋给E。
①ArrayList类底层定义源码:
②创建ArrayList类对象,传入的Dog类型:
(4)Java的泛型可以保证 如果程序在编译时没有发出警告,运行时就不会产生ClassCastException异常。同时,代码更加简洁、健壮。
(5)泛型的作用:可以在类声明时,通过一个标识 表示类中某个属性的类型,或者是某个方法的返回值的类型,或者是参数类型。
例:
①普通定义一个类:
s是String类型的数据,下面的构造器和方法都是String类型,以后在使用中也无法更改。
②使用泛型定义一个类:
定义一个类时,使用E表示泛型(不一定使用E,也可以使用其它字母,但一般使用E或T表示),然后使用E表示s的数据类型,下面的构造器和方法都是E这个数据类型。这个数据类型是在定义Person2的对象时,进行指定的。即 在编译期间,确定E是什么数据类型。
创建对象时指定数据类型:
1.4 泛型的语法
(1)泛型的声明
class类名<E> { } 或 class类名<K, V> { }
interface 接口名<T> { }
说明:
①其中E,T,K,V不代表值,而是表示类型,由程序员自己决定。
②任意大写字母都可以。常用T表示,是Type的缩写。
(2)泛型的实例化
需要在类名后面指定 类型参数 的值(类型)。
例:
2. 注意事项和细节
(1)在泛型实例化,进行类型参数指定时,只能指定引用类型(如:String、Integer、Double),不能是基本数据类型(如:int、double)。
(2)定义泛型使用的标识符一般都是大写字母,如:T、E。
(3)在指定泛型具体类型后,传参可以传入该类型 或 其子类类型。
例:
(4)泛型的使用形式
编译器会进行类型推断,补全< >中的内容,推荐使用简写。
(5)如果在泛型实例化时,没有给泛型指定具体的数据类型,则会默认指定E为Object类型。
3. 自定义泛型
3.1 自定义泛型类
(1)基本语法
class 类名<T, R...> { //…表示可以有多个泛型
//成员
}
例:
(2)使用细节
①普通成员(属性、方法)可以使用泛型。
②使用泛型的数组,不能初始化。因为数组在new的时候,不能确定泛型的类型,无法在内存开空间。
③静态方法和静态属性中不能使用类的泛型。因为静态方法和静态属性是和类相关的,在类加载时,对象还没有创建,就不能确定泛型的类型,JVM就无法完成初始化。
④泛型类的类型,是在创建对象时确定的(因为创建对象时,需要指定确定类型)。
⑤如果在创建对象时,没有指定泛型的类型,默认为Object。
3.2 自定义泛型接口
(1)基本语法
interface 接口名<T, R..> {
//成员
}
例:
(2)使用细节
①接口中,静态成员也不能使用泛型(和自定义泛型类规定一样)。
②泛型接口的类型,在 接口继承接口 或 类实现接口 时确定。
例1:接口继承接口时,指定泛型类型
例2:类实现接口时,直接指定泛型类型
③继承或实现接口时,没有指定泛型的类型,默认为Object。
3.3 自定义泛型方法
(1)基本语法
修饰符 <T, R…> 返回类型 方法名(参数列表) {
}
(2)注意细节
①泛型方法,可以定义在普通类中,也可以定义在泛型类中。
②当泛型方法被调用时,编译器会确定泛型的数据类型,不由程序员直接指定类型。
③在泛型类中,修饰符后 没有泛型标识符 的方法 不是泛型方法,而是使用了声明的泛型。
④泛型方法的参数,可以使用泛型类声明的泛型,也可以使用自己声明的泛型。
4. 泛型的继承和通配符
(1)泛型不具备继承性
(2)<?> 支持任意数据类型
(3)<? extends A> 支持A类以及A类的子类,规定了泛型的上限
(4)<? super A> 支持A类以及A类的父类,不限于直接父类,规定了泛型的下限