知识点:
泛型的概念
泛型类,泛型接口,泛型方法
通配符
? 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集合,分别向集合中加入String,Integer两种类型的数据,这是list会默认都转为Object类型元素,在循环时,Integer类强转成String类型的元素,会报错类型转换异常的错误,这种错误在编译阶段不会显示,只有在运行阶段才会出现
上面再编译阶段不显示错误,是因为list并不清楚自己的存的元素类型,在遍历取出元素时,默认把元素编译改成Object的类型,但是运行时,时元素本身的类型,如果我们让集合一开始存数据时,就知道自己存的数据类型,那么在编译期间可以避免这种错误,泛型就很好解决了这种问题
上面的程序可以这样改一下(加泛型List<String> list=new ArrayList<>();)
二:泛型类,泛型接口,泛型方法
泛型类,泛型接口是传入一个不确定的对象类型,根据实际传入的不同对象,调用相同的方法(在接口,类后面加<E>其中E可以随便定义T,F等等)
泛型方法:方法参数中加入泛型,可以传入不同的类型的对象(在返回值前面加<T>)
//泛型类 public class Parent{ 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 getT(T t){ return t; } //实现数组到集合的复制 public List fromArrayToList(T[] t, List list){ for (T t1:t){ list.add(t1); } return list; } } 测试类 public class Children extends Parent { @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 list=new ArrayList<>(); List list1=c.fromArrayToList(strarr,list); System.out.println(list1); Integer[] strarr1=new Integer[]{ 11,22,33}; List list2=new ArrayList<>(); List list3=c.fromArrayToList(strarr1,list2); System.out.println(list3); }
}
运行结果: 三:通配符 ? (1)统配符的使用
@Test public void Testgenericity3(){ //通配符的使用 Listlist=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 list1=new ArrayList<>();//只能存放null //list1.add(new Grandfather());//错误 //list1.add(new Father()); //错误 //list1.add(new Son()) //错误 list1.add(null); System.out.println(list1); List 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(){ Listlist1=new ArrayList<>(); List list2=new ArrayList<>(); //list1=list2; //若A是B的子类,List ,不是List的子接口 List list=null; //通配符 ? list=list1; List list3=new ArrayList<>(); List list4=new ArrayList<>(); list3=list4; list3=list2; //list3=list1;//错误 List list5=new ArrayList(); list5=list1; list5=list2; //list5=list4;//错误 }
四:补充:
1.不可以在static方法中使用泛型的声明(类加载时,方法已加载,泛型无法确定,初始化对象时,可以确定) 2.不可以在try-catch中使用类的泛型声明