泛型
JDK1.5新特性
优点:
- 类型安全:编译时检测类型
- 减少类型转换
泛型类
概念:在类声明体中用到了类型参数。
语法:
/*
class 类型名<泛型标识,泛型标识, ...>{
private 泛型标示 变量名;
}
*/
public class GenericDemo<T> {
private T key;
public GenericDemo(T key) {
this.key = key;
}
public T getKey() {
return key;
}
public void setKey(T key) {
this.key = key;
}
public static void main(String[] args) {
/*
类名<具体的数据类型> 对象名 = new 类目<具体的数据类型>();
JDK1.7后,可以省略成这样:
类名<具体的数据类型> 对象名 = new 类目<>();
*/
GenericDemo<Integer> integerGenericDemo = new GenericDemo<>(10);
GenericDemo<String> stringGenericDemo = new GenericDemo<>("abc");
//如果没有指定具体的数据类型,此时,操作类型是Object
GenericDemo genericDemo = new GenericDemo("genericDemo");
System.out.println(integerGenericDemo.key);
System.out.println(stringGenericDemo.key);
System.out.println(genericDemo.key);
//泛型类型在逻辑上可以看成是多个不同的类型,但实际上是相同类型
System.out.println(integerGenericDemo.getClass()==stringGenericDemo.getClass()); //输出结果为true
}
}
注意:
- 泛型类只支持类类型,不支持基本数据类型(如int),但可以用包装类(如Integer )
泛型标识<>:类型形参
由外部使用类的时候来指定
泛型标识 | 含义 | |
---|---|---|
T | Type | |
E | Element | |
K | Key | |
V | Value |
泛型类的继承
-
子类也是泛型类,子类和父类的泛型标识要一致。子类也可以扩展泛型标识,但子类中至少有一个泛型标识与父类相同
-
子类不是泛型类,父类要明确泛型的数据类型
//1.子类也是泛型类,子类和父类的泛型标识要一致
class Child<T> extends Parent<T>{}
//也可以扩展,但子类中至少有一个泛型标识与父类相同
class Child<T,E> extends Parent<T>{}
//2.子类不是泛型类,父类要明确泛型的数据类型
class Child extends Parent<String>{}
泛型接口
- 实现类不是泛型类时,接口要明确数据类型
- 实现类也是泛型类时,实现类和接口的泛型类型要一致
泛型方法
泛型方法比泛型类更加灵活
泛型类和泛型方法的区别 | ||
---|---|---|
泛型类 | 实例化类的时候指明泛型的具体类型 | |
泛型方法 | 调用方法的时候指明泛型的具体类型 | |
语法
修饰符 <T,E,...> 返回值类型 方法名(形参列表){
方法体...
}
- public 和 返回类型中间的标识符,可以理解为,声明该方法为泛型方法
- 只有声明了的方法是泛型方法,泛型类中的成员方法不是泛型方法
- 表明,该方法使用泛型类型T,可以使用在返回类型,传入参数列表,方法体里
泛型方法与可变参数
public class GenericDemo<T> {
public static <E> void print(E... e){
for(int i = 0; i < e.length; i++){
System.out.println(e[i]);
}
}
public static void main(String[] args) {
GenericDemo.print(1,2,3,4,5);
GenericDemo.print("a","b","c");
}
}
类型通配符: ?
概念:用“?”代替具体类型,是类型实参,不是类型形参
/*
类型通配符上限
语法:
类/接口 <? extends 实参类型>
作用:要求该泛型的类型只能是《该实参类型或其子类型》
*/
public static void showAnimal(ArrayList<? extends Cat> list){
for(int i;i<list.size();i++){
Cat cat = list.get(i);
System.out.println(cat);
}
}
public static void main(String[] args){
ArrayList<Animal> animals = new ArrayList<>();
ArrayList<Cat> cats = new ArrayList<>();
ArrayList<MiniCat> miniCats = new ArrayList<>();
//showAnimal(animals); 编译报错
showAnimal(cats);
showAnimal(miniCats);
}
/*
类型通配符下限
语法:
类/接口 <? super 实参类型>
作用:要求该泛型的类型只能是《该实参类型或其父类型》
*/
类型擦除
概念:
JDK1.5以前没有泛型,但泛型代码能很好地和之前版本的代码兼容,是因为,泛型信息只存在于代码编译阶段,
在进入JVM之前,与泛型相关的信息会被擦除