知识点:
泛型的概念
泛型类,泛型接口,泛型方法
通配符
? extend A:可以引用A以及子类,只可以存放null
? super A:可以引用A以及父类,可以存放A以及A的子类
参考博客:https://www.cnblogs.com/lwbqqyumidi/p/3837629.html
https://mp.weixin.qq.com/s?__biz=MzIxNzQwNjM3NA==&mid=2247485714&idx=1&sn=7839a7caf10399d59a6a46e9bc5668cd&chksm=97fb07dba08c8ecd5da21ae1f3cede4912f81672ef20d35d840d6a7889abb337c214ac7b9579&scene=0&xtrack=1&key=b2d158037147950fd504ba5526dd4c3f7dd6abf9bde19a33a1abf6e826e1f1c7600f6b07fd9d1905e8125e47c0984426c7ff9b894ff5ef3bf42a04574e4f4f3fe6bdb84178f4acfb2117122a61da2a21&ascene=14&uin=MjEzMzY3MzkzNA%3D%3D&devicetype=Windows+10&version=62060739&lang=zh_CN&pass_ticket=1kSdouT4BHYceycY9n%2FLFiQUOaQQc%2FwAunx2nhzC7rjp%2FsScflTyHbyH3JczQ6hL&winzoom=1
一:什么是泛型,为什么使用方式泛型
(1)什么是泛型
把一个集合中的内容限制为一个特定的数据类型
(2)为什么使用泛型
先看一下一个例子:
public class genTest {
public static void main(String[] args) {
List list=new ArrayList();
list.add("AA");
list.add("BB");
list.add(12);
for (int i=0;i<list.size();i++){
String name=(String)list.get(i);//类型转换
System.out.println(name);
}
}
}
上面程序会报类型转化异常
原因:上面的代码中,我们定义了一个list集合,分别向集合中加入String,Integer两种类型的数据,这是list会默认都转为Object类型元素,在循环时,Integer类强转成String类型的元素,会报错类型转换异常的错误,这种错误在编译阶段不会显示,只有在运行阶段才会出现
上面再编译阶段不显示错误,是因为list并不清楚自己的存的元素类型,在遍历取出元素时,默认把元素编译改成Object的类型,但是运行时,时元素本身的类型,如果我们让集合一开始存数据时,就知道自己存的数据类型,那么在编译期间可以避免这种错误,泛型就很好解决了这种问题
上面的程序可以这样改一下(加泛型List<String> list=new ArrayList<>();)
二:泛型类,泛型接口,泛型方法
泛型类,泛型接口是传入一个不确定的对象类型,根据实际传入的不同对象,调用相同的方法(在接口,类后面加<E>其中E可以随便定义T,F等等)
泛型方法:方法参数中加入泛型,可以传入不同的类型的对象(在返回值前面加<T>)
//泛型类
public class Parent<E> {
private String name;
private E e;
public Parent(){
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public E getE() {
return e;
}
public void setE(E e) {
this.e = e;
}
//声明泛型方法
public <T> T getT(T t){
return t;
}
//实现数组到集合的复制
public <T> List<T> fromArrayToList(T[] t, List<T> list){
for (T t1:t){
list.add(t1);
}
return list;
}
}
测试类
public class Children<E> extends Parent<E> {
@Test
public void Testgenericity1(){
//泛型类,泛型方法
Children c=new Children();
c.setE("AA");
System.out.println(c.getE());
c.setE(12);
System.out.println(c.getE());
//泛型方法
Boolean b1=(Boolean)(c.getT(true));
System.out.println(b1);
Double d1=(Double) (c.getT(11.1));
System.out.println(d1);
String[] strarr=new String []{"AA","BB","CC"};
List<String> list=new ArrayList<>();
List<String> list1=c.fromArrayToList(strarr,list);
System.out.println(list1);
Integer[] strarr1=new Integer[]{11,22,33};
List<Integer> list2=new ArrayList<>();
List<Integer> list3=c.fromArrayToList(strarr1,list2);
System.out.println(list3);
}
}
运行结果:
三:通配符 ?
(1)统配符的使用
@Test
public void Testgenericity3(){
//通配符的使用
List<String> list=new ArrayList<>();
list.add("AA");
list.add("BB");
List<?> slist=list;
//可以读取声明为统配符的集合对象(转成Object)
Iterator<?> iterator=slist.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
//不允许向申明为通配符的集合类中写入对象,但是null可以
//slist.add("AA");
slist.add(null);
}
(2)泛型与继承的关系
? extend A:可以引用A以及子类,只可以存放null
? super A:可以引用A以及父类,可以存放A以及A的子类
(1)? extend A:只可以存放null ? super A:可以存放A以及A的子类
Grandfather、Father、Son三者之间的继承关系
public class Grandfather {
private String name;
private Integer age;
public Grandfather() {
}
}
class Father extends Grandfather {
public Father(){}
}
class Son extends Father {
public Son(){}
}
测试类:
@Test
public void Testgenericity4(){
List<? extends Father> list1=new ArrayList<>();//只能存放null
//list1.add(new Grandfather());//错误
//list1.add(new Father()); //错误
//list1.add(new Son()) //错误
list1.add(null);
System.out.println(list1);
List<? super Father> list2=new ArrayList();//可以存放Father以及Father的子类
list2.add(new Father());
list2.add(new Son());
list2.add(null);
//list2.add(new Grandfather());//错误
System.out.println(list2);
}
运行结果:
(2)? extend A:可以引用A以及子类 ? super A:可以引用A以及父类 (引用后能够添加的元素还是A以及A的子类)
测试类:
@Test
public void Testgenericity2(){
List<Grandfather> list1=new ArrayList<>();
List<Father> list2=new ArrayList<>();
//list1=list2; //若A是B的子类,List<A>,不是List<B>的子接口
List<?> list=null; //通配符 ?
list=list1;
List<? extends Father> list3=new ArrayList<>();
List<Son> list4=new ArrayList<>();
list3=list4;
list3=list2;
//list3=list1;//错误
List<? super Father> list5=new ArrayList();
list5=list1;
list5=list2;
//list5=list4;//错误
}
四:补充:
1.不可以在static方法中使用泛型的声明(类加载时,方法已加载,泛型无法确定,初始化对象时,可以确定)
2.不可以在try-catch中使用类的泛型声明