什么是泛型?泛型就是写模板代码适配类型。优点是不需要强制转换,类型由编译器检查。Listlist=newArrayList<>();这个是泛型的,set限制元素必须是String类型,否则会报错。除了在集合中使用泛型外,许多接口也使用泛型。比如Comparable可以直接对String类型的数组进行排序,因为String实现了Comparable接口publicfinalclassStringimplementsSerializable,Comparable,CharSequenceString[]s={"B","A","C"};Arrays.sort(s);System.out.println(Arrays.toString(s));实习自定义课程的顺序如何?实现Comparable接口publicclassPersonimplementsComparable{Stringname;年龄;publicPerson(Stringname,intage){this.name=name;这个。年龄=年龄;}publicintgetAge(){返回年龄;}publicStringgetName(){返回名称;}@OverridepublicintcompareTo(Persono){returnthis.getAge()-o.getAge();}}测试:Person[]people={newPerson("lucy",21),newPerson("mary",19),newPerson("Mali",33)};系统输出原理tln("排序前");for(Personperson:people){System.out.println(person.getName()+":"+person.getAge());}Arrays.sort(people);System.out.println("Aftersorting");for(Personperson:people){System.out.println(person.getName()+":"+person.getAge());}可以通过控制台找到Person数组输出已经按年龄升序排列WritegenericpublicclassPair{privateTfirst;私人T最后;publicPair(Tfirst,Tlast){this.first=first;this.last=最后一个;}publicTgetFirst(){先返回;}publicTgetLast(){最后返回;}}注意静态方法不能使用,要和实例类型的泛型区分开来:publicstaticPaircreate(Kfirst,Klast){returnnewPair(first,last);}擦除方法虚拟机对泛型一无所知,将所有泛型都视为对象。当需要转换时,编译器会使用T类型自动安全地为我们强制执行,这在使用泛型时会造成一些限制。它不能是基本类型,因为Object不能容纳基本类型。获取类时,由于擦除方式,获取到的对象是同一个对象。泛型不能被实例化泛型对象可以在Class的帮助下被实例化publicPair(Classclazz){first=clazz.newInstance();last=clazz.newInstance();}通用继承publicclassIntPairextendsPair{publicIntPair(Integerfirst,Integerlast){super(first,last);}}子类获取父类Type类型的泛型:publicstaticvoidmain(String[]args){Classclazz=IntPair.class;输入type=clazz.getGenericSuperclass();//获取具有泛型的父类if(typeinstanceofParameterizedType){//判断是否为参数化类型,即泛型ParameterizedTypep=(ParameterizedType)type;类型[]类型=p.getActualTypeArguments();//父类可能有多个泛型类型firstType=types[0];//取第一个泛型类型System.out.println(firstType.getTypeName());}}extends在正常的继承关系中,Integer是Number的子类,但是在泛型中,Pair不是Pair比如我们定义一个方法,限制传入参数为Pair<数>。如果传入Pair,会报错。staticintadd(Pairp){returnp.getFirst().intValue()+p.getLast().intValue();}publicstaticvoidmain(String[]args){Pairp=新对<>(3,5);Pair.add(p);}那么Integer如何传入呢?这就需要使用extends通配符来解决了。修改方法staticintadd(Pairp){returnp.getFirst().intValue()+p.getLast().intValue();}这种通配符称为上界通配符,将泛型T的上限限制为Number使用extends的注意事项:在add()中,无法获取到Integer的引用。无法编译以下代码。您需要强制TransformIntegerfirst=p.getFirst();因为虽然我们把泛型的上界限定为Number,但是我们并不知道传入的具体类型是Integer还是Number的另一个子类。编译器只能确定它必须是Number的子类,不能将Number的子类型传递给对象的set()p.setFirst(newInteger(p.getFirst().intValue()+100));总结一下:允许调用get()获取对Number的引用不允许调用set(?extendsNumber)传入任何Number引用。Super与Number正好相反。Integer及其父类Pair被传入。使用super的注意事项:publicstaticvoidmain(String[]args){Pairp=newPair<>(3,5);Pair.add(p,5);}staticvoidadd(Pairp,Integern){p.setFirst(n);}这段代码可以正常编译,因为下界限制为Integer,可以传递Integer或者它的父类,但是不能用Integer来接收get()的返回值,因为无法确定具体的返回值是Integer还是它的父类,唯一可以的被接收的是Objectstaticvoidadd(Pairp,Integern){Objectfirst=p.getFirst();}所以比较extends和super,我们可以发现:可读但不可写writableandunreadable补充声明泛型数组时,不能使用new操作符创建数组。需要转换Pair[]pairs=(Pair[])newPair[2];