我们查看API帮助文档可知,Collection接口的定义格式为Interface Collection<E>,那么<E>代表什么呢?E - 此集合中元素的类型 !为什么要用<>括起来呢?就是我们将要学习到的泛型。
学习思路:
泛型的通配符:
泛型中的通配符有四种:T、E、K V、?
泛型有以上四种定义格式;
T Java的类型的是一个形参!在方法声明的时候使用。一般指代泛型类。
E 通常用于规定集合中的元素类型。
K V 一般表示Java中Map集合的键值对。
?一般表示不确定的Java类型,这是一种无限的符号,代表任何类型都可以。是一个实参!在方法使用的时候直接调用,但是 ?不能作为元素类型添加值,也就是 ?只能在没有定义元素类型的时候接收不同类型的元素。
?一般只是接收某种数据类型,并不能作为返回值;
?extends XX:向下限定,E及其子类;
? super XX:向上限定,E极其父类。
(在后面详细讲解 ?请继续学习。)
在学习Collection集合的时候,我们了解到,集合可以存储任意类型的元素,那么我们如果在使用增强for循环遍历集合的过程中,不使用Object接收对象,而使用特定的元素类型,就会爆出ClassCastException异常,表示类型转换异常,类型不兼容;
publicstaticvoidmain(String[] args) { //此处指定了Collection集合的类型为Integer,所以不能添加别的元素类型Collection<Integer>num=newArrayList(); num.add(123); num.add(456); num.add(789); // num.add("123");在编译的时候都会报错//我们定义了一个没有指定类型的Collection集合Collectionstr=newArrayList(); str.add("123"); str.add("456"); str.add("789"); //因为指定集合的元素类型<E>,只会在编译的时期判断,存入的内容类型//在运行时会把元素类型都默认为Object类型,这就叫做“泛型的擦除”num.addAll(str); //在增强for循环的时候我们使用了Integer作为元素输出类型//但是num集合中是存在String类型的元素的,所以会存在类型不兼容无法完成遍历for (Integerin : num){ System.out.println(in); } }
泛型,用来灵活地将数据类型应用到不同的类、方法、接口当中。将数据类型作为参数进行传递。
泛型类:
<数据类型> 此处的数据类型只能是引用类型。
好处:
A:把运行时期的问题提前到了编译期间 ;
B:避免了强制类型转换。
/** 泛型类:把泛型定义在类上*/publicclassObjectTool<T> { privateTobj; publicTgetObj() { returnobj; } publicvoidsetObj(Tobj) { this.obj=obj; } }
/** 泛型类的测试*/publicclassObjectToolDemo { publicstaticvoidmain(String[] args) { ObjectTool<String>ot=newObjectTool<String>();//规范了数据的存储ot.setObj(newString("江一燕")); Strings=ot.getObj(); System.out.println("姓名是:"+s); ObjectTool<Integer>ot2=newObjectTool<Integer>(); ot2.setObj(27); Integeri=ot2.getObj(); System.out.println("年龄是:"+i); } }
泛型方法:
修饰符 <代表泛型的变量> 返回值类型 方法名 (参数){ }
//普通方法//修饰符 返回值类型 方法名(参数){}publicintshow(inti){ returni; } /** 泛型方法:把泛型定义在方法上*/public<T>Objectshow(Tt) { returnt; } //定义一个泛型方法//返回类型不应该明确,因为泛型方法的类型都不明确//建议:Object 或者 T(泛型)public<T>Tshow(Tt){ returnt; }
//实现类publicclassTestCollection { public<T>Objectshow(Tt){ returnt; } public<T>Tshow2(Tt){ returnt; } publicintshow(inti){ returni; } publicstaticvoidmain(String[] args) { System.out.println(newTestCollection().show(1111111111)); System.out.println(newTestCollection().show("2222222222")); System.out.println(newTestCollection().show2(newDate())); } } /*11111111112222222222Tue May 03 16:03:35 CST 2022*/
泛型接口:
修饰符 interface 接口名<代表泛型的变量> { }
/** 泛型接口:把泛型定义在接口上*/publicinterfaceInter<T> { publicabstractvoidshow(Tt); }
//实现类在实现接口的时候//第一种情况:已经知道该是什么类型的了publicclassInterImplimplementsInter<String> { publicvoidshow(Stringt) { System.out.println(t); } } //第二种情况:还不知道是什么类型的publicclassInterImpl<T>implementsInter<T> { publicvoidshow(Tt) { System.out.println(t); } }
//测试类publicstaticvoidmain(String[] args) { //第一种情况:实现类已经明确类型,实例化对象时必须与实现类中的类型一致InterDemo<String>i=newInteImpl();//我在实现的时候,已经明确类型--Stringi.show("aaa"); i.show("bbb"); //第二种情况:实现类也没有明确类型InterDemo<Integer>ii=newInteImpl2<>();//我在实现的时间也没有给出明确ii.show(11); ii.show(22); InterDemo<String>ii2=newInteImpl2<>();//我在实现的时间也没有给出明确ii2.show("11"); ii2.show("22"); } }
当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符<?>表示。但是一旦使用泛型的通配符后,只能使用Object类中的共性方法,集合中元素自身方法无法使用。
关于 ?通配符:
泛型的通配符:不知道使用什么类型来接收的时候,此时可以使用?,?表示未知通配符。此时只能接受数据,不能往该集合中存储数据。
/** 泛型高级(通配符)* ?:任意类型,如果没有明确,那么就是Object以及任意的Java类了* ? extends E:向下限定,E及其子类* ? super E:向上限定,E极其父类*/publicclassAnimal { } publicclassDogextendsAnimal { } publicclassCatextendsAnimal { } publicclassGenericDemo { publicstaticvoidmain(String[] args) { // 泛型如果明确的写的时候,前后必须一致Collection<Object>c1=newArrayList<Object>(); //错误写法:// Collection<Object> c2 = new ArrayList<Animal>();// Collection<Object> c3 = new ArrayList<Dog>();// Collection<Object> c4 = new ArrayList<Cat>();// ?表示任意的类型都是可以的Collection<?>c5=newArrayList<Object>(); Collection<?>c6=newArrayList<Animal>(); Collection<?>c7=newArrayList<Dog>(); Collection<?>c8=newArrayList<Cat>(); // ? extends E:向下限定,E及其子类,表示包括E在内的任何子类;// Collection<? extends Animal> c9 = new ArrayList<Object>();Collection<?extendsAnimal>c10=newArrayList<Animal>(); Collection<?extendsAnimal>c11=newArrayList<Dog>(); Collection<?extendsAnimal>c12=newArrayList<Cat>(); // ? super E:向上限定,E极其父类,表示包括E在内的任何父类;Collection<?superAnimal>c13=newArrayList<Object>(); Collection<?superAnimal>c14=newArrayList<Animal>(); // Collection<? super Animal> c15 = new ArrayList<Dog>();// Collection<? super Animal> c16 = new ArrayList<Cat>(); } }