Java巩固之路-----泛型

泛型

泛型的定义

泛型,即“参数化类型”。就是将类型由原来的具体的类型参数化,在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型

泛型的意义

编译期间确定类型,保证类型安全

避免强制转换的类型

提高代码的重用率,增加代码的通用灵活性

泛型的类型擦除

泛型,只在编译期间有效。泛型类型在逻辑上可以看成多个不同类型,但实质上,他们还是同一类型,编译之后程序会采取去泛型化措施。

Java巩固之路-----泛型

上图代码中,list的初始化,定义了参数类型为Integer,所以插入String类型的时候,类型检查会报错。

但是,我们如果通过反射的方式,在代码运行阶段向定义容器类型为Integer的list中插入String对象,插入成功,长度增加了。

Java巩固之路-----泛型

这就是泛型擦除。

泛型的使用

泛型可以用来接口、类、方法三个层次,但不管使用在何层次,都需要先用<> 加通配符的形式来声明,这是一个泛型。

泛型接口

public interface Deque<E> extends Queue<E> 

在接口声明时加上<E>说明这是个泛型接口。

泛型接口的实现方式:

1、实现类继续使用泛型来表示

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable

LinkedList作为Deque的实现类,不指定泛型的参数,继续使用<E>来表示

2、为接口指定固定的类型

public class ListAdapter extends AbstractList<Object> implements RandomAccess, Deque<Object>

ListAdapter实现了Deque的同时,指定泛型为Object。

泛型类

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

ArrayList中定义了容器内数据类型为泛型,因此,我们只需要在创建ArrayList对象的时候确定数据类型就可以向其中存入我们想存储类型的数据

泛型方法


1、在FanClass类中我们声明一个泛型为T,他其中的方法如sys(T t)可以直接使用T来作为参数的类型,因为这个T在类层次已经声明。

2、我们也可以在方法层次重新一个泛型,使用<KK>来声明。KK代表一个泛型

public <KK> KK getNode(KK k){

   return k;
}

3、静态泛型方法中不能使用类中定义的泛型,必须使用静态泛型方法自己定义的新的泛型。因为静态方法是在JVM加载阶段就会被加载的方法,而类中的泛型只会在对象初始化的时候才会被用户指定。所以类层次的泛型对于静态方法来说,是不存在的,所以无法使用。

泛型的上下界

在泛型的使用过程中,我们也可以通过关键字的方式来指定传入参数的类型范围。

泛型的上界

泛型的上界,我们使用<? extent 上限>来表示。

Java巩固之路-----泛型

用<T extends Number>来声明这个泛型类的参数只能是Number和继承了Number的子类。由此来决定上限

泛型的下限

泛型的下限,使用<? super 下限>

Java巩固之路-----泛型

通过这种方式,我们确定参数类型的下限只能是Integer和Integer的子类。