泛型(Generic)
在编译阶段识别泛型,但是在jvm运行之前就将泛型的痕迹擦除
泛型即参数化类型,在jdk1.5的版本之后才开始的概念
参数化类型?
将一种数据类型以参数的形式传递给类,接口,方法中
好处:可以将运行期间的问题提前到编译阶段进行检查
泛型接口:
public interface List<E> extends Collection<E>{}
泛型类:
public class ArrayList<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializable
泛型方法:
static <T> List<T> asList(T... a)
返回有指定数组支持的固定大小的列表
泛型标记命名是可以自定义的
jdk中常见的泛型的名称有:
K(key键)
V(value值)
E(Element元素)
T(Type类型)
<?>通配符 任意的类型都可以 Object
public class MyClass<I,F,D> {
//访问控制修饰符 返回值数据类型 方法名(参数列表){
// 方法体;
// }
public I add(I a,I b){
System.out.println(a);
System.out.println(b);
return null;
}
public static void main(String[] args){
//创建对象的时候指定数据类型
MyClass<Integer,Float,Double> mc = new MyClass<>();
Integer x = mc.add(10,20);
MyClass<Double,Float,Integer> m = new MyClass<>();
}
}
泛型上下边界的限定<? extends E><? super E>
<? extends E> 是 Upper Bound(上限)的通配符,用来限制元素的类型的上限的 比如:
List<? extends Fruit> fruits;
表示集合中的元素类型上限为Fruit类型,即只能是Fruit或者Fruit的子类,因此对于下面的
赋值合理的是:
fruits = new ArrayList<Fruit>();
fruits = new ArrayList<banana>();
如果集合中的元素类型为Fruit的父类就会出现错误,比如:
fruits = new ArrayList<Object>();//出现编译不通过的情况
/**
* 1、写入:
* 因为集合fruits中装的元素类型为Fruit或者它的子类,直觉告诉我们,往集合中添加一个
* fruit类型的元素或者它的子类对象是可行的
* fruits.add(new Fruit());
* fruits.add(new Banana());
* 结果都是编译不通过.为什么呢?
* 因为<? extends Fruit>只能够告诉编译器,集合中元素类型的上限,但是具体是什么
* 类型编译器不知道,fruits可以指向ArrayList<Fruit>,也可以指向:ArrayList<Banana>
* ArrayList<Apple>,也就是说它的类型是不确定的,既然不确定,为了安全性起见,
* 编译器只能阻止添加元素
*
* 2、读取
* 无论fruits指向指向什么,编译器都可以确定获取的元素是Fruit类型,
* 所以读取集合中的是被允许操作的,代码是可以编译通过的
*
*/
<? super E>是Lower Bound(下限)的通配符,用来限制元素的类型下限,比如:
List<? super Apple> apples;
表示集合中的元素的类型下限是Apple类型,即只能是Apple或者Apple的父类,
因此合理的赋值:
apples = new ArrayList<Apple>();
apples = new ArrayList<Fruit>();
apples = new ArrayList<Object>();
如果Apple的兄弟类和子类会编译失败
/**
* 写入:
* 因为apples中装得元素是Apple或者Apple的父类,我们无法确定是哪个具体的但是,
* 但是可以确定Apple就是Apple,所以可以添加进去一个元素。
* 如果apple还有子类,Apple和Apple的子类和一个不确定类型的类:比如隔壁的banana
* 就无法正常兼容,我们可以添加apple但是为了安全性起见,不能添加别的类进来
*
* 读取:
* 无法确定读取出来的是什么类型,所以给到了一个Object类型的变量中,
* 然后需要进行强制转换
*/
public class Animal {
}
--------------------------------------------------------
public class Cat extends Animal{
}
--------------------------------------------------------
public class Dog extends Animal{
}
--------------------------------------------------------
public class Test {
public static void main(String[] args) {
//上限:
//<? extends 父类>
//ArrayList<? extends Animal> animals = new ArrayList<Object>();
ArrayList<? extends Animal> animals = new ArrayList<Animal>();
ArrayList<? extends Animal> animals1 = new ArrayList<Dog>();
ArrayList<? extends Animal> animals2 = new ArrayList<Cat>();
//下限
//<? super 子类>
ArrayList<? super Dog> dogs = new ArrayList<Object>();
ArrayList<? super Animal> arrayList = new ArrayList<Animal>();
ArrayList<? super Dog> dogs1 = new ArrayList<Dog>();
//ArrayList<? super Dog> dogs2 = new ArrayList<Cat>();
//赋值
ArrayList<Dog> dogs2 = new ArrayList<Dog>();
dogs2.add(new Dog());
dogs2.add(new Dog());
dogs2.add(new Dog());
ArrayList<? extends Animal> animals3 = dogs2;
System.out.println(animals3.size());
ArrayList<Animal> animals4 = new ArrayList<Animal>();
animals4.add(new Animal());
animals3 = animals4;
System.out.println("----" + animals3.size());
ArrayList<Object> objects = new ArrayList<Object>();
objects.add(new Object());
//ArrayList<? extends Animal> animals4 = objects;
ArrayList<Dog> dogs3 = new ArrayList<Dog>();
dogs3.add(new Dog());
ArrayList<? super Dog> dogss = dogs3;
dogss = objects;
dogss = animals4;
}
}