多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
[TOC] # 泛型 由于集合中什么类型的元素都可以存储,导致取出时候,如果出现强转就会引发运行时错误. 解决,使用集合必须明确集合中元素的类型,这种方式称之为泛型 ![](https://box.kancloud.cn/9248e8998323f452db92a43104f11bfa_463x360.png) ## 泛型的好处 泛型的好处 a:将运行时期的ClassCastException,转移到了编译时期变成了编译失败。 b:避免了类型强转的麻烦。 演示下列代码: ~~~ public class GenericDemo { public static void main(String[] args) { List list = new ArrayList(); list.add("abc"); list.add("123"); //list.add(5);//当集合明确类型后,存放类型不一致就会编译报错 //集合已经明确具体存放的元素类型,那么在使用迭代器的时候,迭代器也同样会知道具体遍历元素类型 Iterator<String> it = list.iterator(); while(it.hasNext()){ String str = it.next(); System.out.println(str.length()); //当使用Iterator<String> //控制元素类型后,就不需要强转了。获取到的元素直接就是String类型 } } } ~~~ ## 泛型的通配符 **? 可以接收任意的泛型类型,只能够取出,不能够修改** ~~~ public class GenericDemo { public static void main(String[] args) { ArrayList array = new ArrayList(); HashSet<Integer> set = new HashSet<Integer>(); array.add("123"); array.add("456"); set.add(789); set.add(890); iterator(array); iterator(set); } /* * 定义方法,可以同时迭代2个集合 * 参数: 怎么实现 , 不能写ArrayList,也不能写HashSet * 参数: 或者共同实现的接口 * 泛型的通配,匹配所有的数据类型 ? */ public static void iterator(Collection<?> coll){ Iterator<?> it = coll.iterator(); while(it.hasNext()){ //it.next()获取的对象,什么类型 System.out.println(it.next()); } } } ~~~ ## 泛型的限定 ~~~ / * 将的酒店员工,厨师,服务员,经理,分别存储到3个集合中 * 定义方法,可以同时遍历3集合,遍历三个集合的同时,可以调用工作方法 / import java.util.ArrayList; import java.util.Iterator; public class GenericTest { public static void main(String[] args) { //创建3个集合对象 ArrayList cs = new ArrayList(); ArrayList fwy = new ArrayList(); ArrayList jl = new ArrayList(); //每个集合存储自己的元素 cs.add(new ChuShi("张三", "后厨001")); cs.add(new ChuShi("李四", "后厨002")); fwy.add(new FuWuYuan("翠花", "服务部001")); fwy.add(new FuWuYuan("酸菜", "服务部002")); jl.add(new JingLi("小名", "董事会001", 123456789.32)); jl.add(new JingLi("小强", "董事会002", 123456789.33)); // ArrayList arrayString = new ArrayList(); iterator(jl); iterator(fwy); iterator(cs); } ~~~ ~~~ /* * 定义方法,可以同时遍历3集合,遍历三个集合的同时,可以调用工作方法 work * ? 通配符,迭代器it.next()方法取出来的是Object类型,怎么调用work方法 * 强制转换: it.next()=Object o ==> Employee * 方法参数: 控制,可以传递Employee对象,也可以传递Employee的子类的对象 * 泛型的限定 本案例,父类固定Employee,但是子类可以无限? * ? extends Employee 限制的是父类, 上限限定, 可以传递Employee,传递他的子类对象 * ? super Employee 限制的是子类, 下限限定, 可以传递Employee,传递他的父类对象 */ public static void iterator(ArrayList<? extends Employee> array){ Iterator<? extends Employee> it = array.iterator(); while(it.hasNext()){ //获取出的next() 数据类型,是什么Employee Employee e = it.next(); e.work(); } } ~~~ ## 泛型接口 定义泛型接口 ~~~ public interface IMessage<T> { public void print(T t); } ~~~ 在接口上必须要定义其相应的子类,所以来讲如果要定义子类有两种形式 **形式一: 在子类继续设置泛型** ~~~ class MessageImpl<T> implements IMessage<T> { @Override public void print(T t) { System.out.println(t); } } class TestDemo { public static void main(String[] args) { IMessage<String> msg = new MessageImpl<String>(); msg.print(" hello world "); } } ~~~ **形式二: 在子类不设置泛型,而为父接口明确的定义一个泛型类型** ~~~ class MessageImpl implements IMessage<String> { @Override public void print(String s) { System.out.println(s); } } class TestDemo { public static void main(String[] args) { IMessage<String> msg = new MessageImpl(); msg.print(" hello world "); } } ~~~ ## 泛型方法 泛型方法不一定非要定义在支持泛型的类里面.在之前所编写的所有存在有泛型的方法都是在泛型支持类里面定义的 泛型方法定义 ~~~ //定义一个含有泛型的方法 publicvoidmethod01(Mm){ System.out.println(m); } ~~~ ~~~ //定义一个含有泛型的静态方法 publicstaticvoidmethod02(Ss){ System.out.println(s); } ~~~ ~~~ class TestDemo { public static void main(String[] args) { String hello = fun("hello"); System.out.println(hello.length()); } //T的类型由传入的参数类型决定 public static <T> T fun(T t) { return t; } } ~~~ ## 泛型对象 ~~~ class Show<E> { private E name; public E getName() { return name; } public void setName(E name) { this.name = name; } } public class App { public static void main(String[] args) { Show<Integer> res = new Show<>(); res.setName(11); System.out.println(res.getName()); } } ~~~