参考文章:https://segmentfault.com/a/1190000014120746
泛型
1.泛型简介
泛型,可以理解为“参数化类型”。本意是将原来固定的类型参数化,可以类比于方法参数,当调用的时候才决定参数值;而泛型就是在调用时才决定究竟是什么类型。
泛型可以用在类、方法、接口上。(比如各种容器类)
2.泛型的特性
只在编译器有效而在运行时无效,举个例子:
public class Test {
public static void main(String[] args) {
List<String> array1 = new ArrayList<String>();
List<Integer> array2 = new ArrayList<Integer>();
Class classArray1= array1.getClass();
Class classArray2 = array2.getClass();
System.out.println(classArray1);
System.out.println(classArray2);
if(classArray1.equals(classArray2)){
System.out.println("泛型测试类型相同");
}
}
}
运行结果:
从这里可以看出不管对象是什么类型,本质上都还是ArrayList类的对象
3.使用
3.1 泛型类
public class Test<E>{//实例化对象时必须将E指定为具体类型
private T num;
public Test(T num){
this.num=num;
}
public T getNum(){
return num;
}
}
3.1.1泛型类
3.2 泛型接口
public interface Test2<T>{
public T next();
}
3.2.1 实现泛型接口,未传入泛型实参
//实例化对象的时候再决定T的类型
class Demo<T> implements Test2<T>{
public T next(){
return null;
}
}
3.2.2 实现泛型接口,传入泛型实参
//注意这里是在接口内确定实参后再被类实现,只要确认了实参类型,里面方法,属性的类型也就确定了
class Demo implements Test2<String>{
public String next(){
return "abc";
}
}
3.3 泛型方法
public <T> void show(T t){
System.out.println(t);
}
3.4 类型通配符
用途:假设要把集合作为一个参数传递到方法中,最好在形参的参数类型中确定好集合里参数的类型,但我们并不清楚要传入的集合类型,这时候就要用到类型通配符了
public void test(List<?> list){
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
}
//但是在这种方法里不能使用对象与类型有关的方法,比如add();因为我现在并不知道对象的类型是什么
3.4.1 设定通配符的上下限
List<? extends Number>
//表示只能操纵数字类型的元素【Float、Integer、Double、Byte】
List<? super Type>
//只能传入Type和Type的父类
3.5 泛型擦除
编译器编译完带有泛形的java程序后,生成的class文件中将不再带有泛形信息,以此使程序运行效率不受到影响,这个过程称之为“擦除”。