1、 泛型
泛型本质是指类型参数化。
允许在定义类、接口、方法时使用类型形参,当时用时指定具体类型。
所有使用该泛型参数的地方都被统一化,保证类型一致。如果未指定类型,默认是object类型。集合体系中所有的类型增加了泛型,泛型主要用于集合。
2、 泛型的优势
1) 不需要强转
2) 更安全
3) 可见性好
3、 使用
1) 泛型类(用在类的上面)
static class ObjectTool {
private T obj;
public T getObj() {
return obj;
}
public void setObj(T obj) {
this.obj = obj;
}
}
2) 泛型方法(用在方法上面)
public class MethodGenericity {
public static void main(String[] args) {
//创建对象
ObjectTool tool = new ObjectTool();
//调用方法,传入的参数是什么类型,返回值就是什么类型
tool.show("hello");
tool.show(12);
tool.show(12.5);
}
static class ObjectTool {
//定义泛型方法..
public <T> void show(T t) {
System.out.println(t);
}
}
}
3) 泛型类派生的子类
/**
- 把泛型定义在接口上
*/
interface Inter {
void show(T t);
}
/**
- 子类明确泛型类的类型参数变量
*/
class InterImpl1 implements Inter {
@Override
public void show(String s) {
System.out.println(s);
}
}
/**
- 子类不明确泛型类的类型参数变量,实现类也要定义出T的类型
*/
class InterImpl2 implements Inter {
@Override
public void show(T t) {
System.out.println(t);
}
}
1、 泛型通配符
public void test3(List<?> list) {
for (int i = 0; i < list.size(); i++) {
// list.add(list.get(0)); // 编译错误
System.out.println(list.get(i));
}
}
public void test4(List list) {
for (int i = 0; i < list.size(); i++) {
// list.add(list.get(0)); // 编译阶段ok,但是运行时抛异常,Exception in thread "main" java.lang
// .UnsupportedOperationException
System.out.println(list.get(i));
}
}
2、 泛型的上限和下限
泛型的上限:
格式:类型名称<? Extends 类> 对象名称
意义:只能接受该类型及其子类
泛型的下限:
格式:类型名称<? super 类> 对象名称
意义:只能接受该类型及其父类
PECS法则
总结 ? extends 和 ? super 通配符的特征,我们可以得出以下结论:
如果你想从一个数据类型里获取数据,使用 ? extends 通配符
如果你想把对象写入一个数据结构里,使用 ? super 通配符
3、 类型擦除和桥接方法
泛型是提供给javac编译器使用的,它用于限定集合的输入类型,让编译器在源代码级别上,即挡住向集合中插入非法数据。但编译器编译完带有泛形的java程序后,生成的class文件中将不再带有泛型信息,以此使程序运行效率不受到影响,这个过程称之为 “擦除”
由于类型被擦除了,为了维持多态性,所以编译器就自动生成了桥接方法
/**
-
桥接方法
-
1> 类型擦除 javac ——> class 泛型被擦除了!
-
2> 泛型虽然被擦除了,但是,你一定要给我保留泛型的行为!
-
@param <>
*/