泛型总结
在JDK1.5 以前,如果把数据存入到集合的时候,需要去判断类型是否合法,假如定义了一个List类型的集合,先向其中加入了两个字符串类型的值,随后加入一个Integer类型的值。这是完全允许的,因为此时list默认的类型为Object类型。在之后的循环中,由于忘记了之前在list中也加入了Integer类型的值或其他编码原因,编译是可以的,但是运行时就会报出ClassCastException,这是严重的安全隐患,而在1.5之后,引入了泛型并且使用了泛型之后,这个隐患在编译时期就被暴露出来,便于开发者去避免这种隐患,也避免了进行强制转换。可以把泛型理解为是java的一种安全机制,对于使用会更方便
泛型的定义:
第一种:定义在类 或者接口上边。把尖括号放在类名后边.访问区域是整个类里边,但是,静态方法无法访问这个泛型。
注意:跟在类后边,是用来声明一个泛型的。其他地方不是赋值,就是使用
第二种: 定义在方法上。规则:定义在修饰符之后,返回值之前。
如:自定义的泛型
public class Holder<LOL> {
LOL o;
public void set(LOL t) {
this.o = t;
}
public LOL get()
{
return this.o;
}
public static <LOL> void print(LOL l)
{
System.out.println(l);
}
}
自定义的泛型,可以理解为一个变相的类这里面的规则都是自定义的规则,使用起来会更方便
对于自定义泛型的几种使用方法:
什么时候赋予具体的数据类型:用的时候,就要赋予数据类型 --不一定为具体的数据类型
类的泛型:
1、在这个类创建的时候,泛型有了具体的数据类型
2、在这个类被实现的时候,必须给与这个需要泛型的类一个数据类型。
可以为一个具体的数据类型,也可以是一个新的泛型,如果没显示的设置数据类型,则默认父类的泛型里使用Object
方法的泛型:
是在调用的时候,有了具体的数据类型
通配符:
把泛型参数理解成方法参数,当我们的对象类型不明确时可以用一个通配符”?”来表示,通配符代表任意类型,相当于是一个占位符,执行的时候回被具体的类型所替代。看一个例子,加入想实现一个能够遍历所有类型的ArrayList的通用方法,由于实现前并不知道到底有多少类型我们需要打印,而使用Object又可能导致ClassCastException,此时通配符的优势便出现了
使用通配符:
泛型的限定
-------------------------上限<? extends E>,下限<? super E>
由于泛型不支持向上转型
使用通配符就能解决基本上的问题,通用遍历简单类型的集合,但是要保存的是对象呢?要遍历的对象之间又存在继承关系呢?很明显通配符当然可以,但是并不是所有类型的数据我们都想要的,我们想只要有关系的类型(继承关系)。
格式:
<? extends E> : E类型或者是E类型的子类: 限定类型的上限.
<?> 等价于 <? extends Object>
<? super E> : E类型,或者E类型的父类 : 限定了类型的下限
写在泛型定义的时候
格式:<E extends Person> 泛型E只能接受Person以及Person的子类
之前的定义方式<E> 就相当于 <E extends Object>
<E extends Student> 这样泛型E就只能接受Student以及Student的父类
这是 不使用限定的情况下遍历的:
因为泛型无法自动向上转型! ! !
这是使用泛型限定之后的效果:
对于泛型的限定来说,同时也可以在初始化把限定条件加上
1、 类上的泛型限制
class Holder<T extends Person>
{
}
2、方法上的泛型限制:
public static <T extends Person> void print(T t)
{
}