泛型起到的作用就是将类型参数化,在不创建新类的情况下通过创建对象实例或应用时确定具体的数据类型,以提高代码的复用性以及用以解决类型爆炸问题。
例如集合类中使用了泛型,可以存储任意的对象,这些对象公用集合类中定义的方法和处理逻辑,不需要为每个对象重新定义集合类,实现了代码复用以及防止了类型爆炸问题。
例如ArrayLlist泛型类,虽然在实例化对象时可以指定具体的泛型变量类型,但是都对应同一个类对象:
上面的代码声明了两个ArrayList实例对象并指定的具体的泛型值,从上面的代码的运行结果来看它们具有相同的class对象。strList和intList在编译时是两个不同的类型,但是在编译完成后会进行类型擦除,我们可以使用java反编译工具进行类型擦除验证:
执行命令:jad -sJava Demo.class
结果:
通过上面的实验,可以得到的结论就是在进行代码编译后进行了泛型的类型擦除操作。
编译前:
编译后:
对class使用jad进行反编译:jad -sJava Demo.class
以集合容器为例,如果使用Object在运行的时候需要进行手动的强制类型转换,可能出现类型转换异常;但是在编译期没有任何的错误提示。
如果使用泛型在编译期进行类型安全性检查,避免运行时出现类型转换异常。
泛型可以定义在类、接口和方法中,分别称为泛型类、泛型接口和泛型方法
把泛型定义在类上。格式为:修饰符class 类名<泛型类型1,…>
示例演示:
ublic class Tool<Q> {
private Q q;
public Q getObj(){
return q;
}
public void setObj(Q q) {
this.q = q;
}
把泛型定义在接口上,格式:修饰符 interface接口名<泛型类型>
示例演示:
interface Inter<T> {
public void show(T t);
}
把泛型定义在方法上,格式:修饰符 <泛型类型> 返回值类型 方法名(类型 变量名) { }。
示例演示:
public <T> void demo(T t) {
//具体方法逻辑
}
泛型通配符<?>, 表示任意类型;如果没有明确指定那么就表示Object以及任意的Java类型。