1.泛型出现的背景
JAVA推出泛型以前,程序员可以构建一个元素类型为Object的集合,该集合能够存储任意的数据类型对象,而在使用该集合的过程中,需要程序员明确知道存储每个元素的数据类型,否则很容易引发ClassCastException异常。
2.泛型的理解和好处
使用传统方法的问题(不使用泛型)
(1)不能将加入到几个中的数据类型进行约束(不安全),进行转型可能会出现ClassCastException
(2)遍历的时候,需要进行类型转换,如果集合中的数据量较大,对效率有影响
3.什么是泛型?
(1)泛型,即参数化类型。可以理解为,广泛的类型,可以表示数据类型的数据类型。是jdk5.0出现的新特性,用于解决数据类型的安全性问题。
(2)我们平时用的ArrayList就使用了泛型,List<T> list = new ArrayLIst<>();
①其中,T不代表值,而是表示类型
②任意字母都可以。常用T表示,是Type的缩写
(3)泛型把运行时异常,转到了编译时异常。只要程序编译时没有问题,就不会产生ClassCastException。
(4)泛型可以在类声明时通过一个标识表示类中某个属性的类型,或者某个方法的返回值的类型,或者是参数类型
public class Person<E> {
E s; //E表示s的数据类型,该数据类型在定义Person对象的时候指定,即在编译期间,就确定E是什么类型
public Person(E s){ //E也可以是参数类型
this.s = s;
}
public E f(){ //返回类型使用E
return s;
}
}
4.泛型的定义与使用
(1)泛型的说明
interface 接口<T>{}
和class 类<K,V>{}
说明:
①其中T,K,V不代表值,而是表示类型(只能是引用类型,不能是基本数据类型)
②任意字母都可以。常用T表示,是Type的缩写
③在给泛型指定具体类型后,可以传入该类型或者子类类型
(2)泛型的实例化要在类名后面指定类型参数的值(类型),如:
List<String> strList = new ArrayList<String>();
(2)普通成员(属性,方法)可以使用泛型。静态成员(静态成员、静态方法)不能使用泛型(因为静态是和类相关的,在类加载时,对象还没有创建,泛型是在类创建的时候指定的)
(3)使用泛型的数组,不可以初始化
(4)泛型类的类型,是在创建对象时确定的,没有指定类型,默认为Object
例如:List list = new ArrayList(); 等价于 List<Object> list = new ArrayList<Object>();
4.1 泛型类
(1)泛型类的定义语法
class 类名称 <泛型标识1,泛型标识2,…> {
private 泛型标识1 变量名;
private 泛型标识2 变量名;
.....
}
(2)泛型类的使用语法
①类名<具体的数据类型> 对象名 = new 类名<具体的数据类型>();
②Java1.7以后,后面的<>中的具体的数据类型可以省略不写
(3)泛型类的注意事项
①泛型类,如果没有指定具体的数据类型,此时,操作类型是Object
②泛型的类型参数只能是类类型,不能是基本数据类型
③泛型类型在逻辑上可以看成是多个不同的类型,但实际上都是相同类型
(4)从泛型类派生子类
①子类也是泛型类,子类和父类的泛型类型要一致
class 子类<T> extends 父类<T>
②子类不是泛型类,父类要明确泛型的数据类型
class 子类 extends 父类<指定类型>
4.2 泛型接口
(1)泛型接口的定义
interface 接口名称 <泛型标识1,泛型标识2,…> {
泛型标识1 方法名();
泛型标识2 方法名();
.....
}
(2)泛型接口的使用
①实现类不是泛型类,接口要明确数据类型
②实现类也是泛型类,实现类和接口的泛型类型要一致
③泛型接口的类型,在继承接口或者实现接口时确定
4.3 泛型方法
①泛型类,是在实例化类的时候指明泛型的具体类型。
②泛型方法,是在调用方法的时候指明泛型的具体类型
(1)语法
修饰符 <泛型列表T,E,...> 返回值类型 方法名(参数){
方法体...
}
public <T> void fly(T t) { }
(2)使用
①修饰符与返回值中间泛型列表非常重要,可以理解为声明此方法为泛型方法。
②只有声明了泛型列表的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法。
③<T>
表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T。
④与泛型类的定义一样,此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型。
(3)注意
下面run方法不是泛型方法,而是使用了“类声明的泛型”
class Dog<T>{
public void run(T t) { }
}
4.4 泛型通配符
(1)<?>: 支持任意泛型类型
(2)<? extends A>:支持A类以及A类的子类,规定了泛型的上限
(3)<? super A>:支持A类以及A类的父类,不限于直接父类,规定了泛型的下限