Generic——可以接收数据类型的数据类型。本文将从总体上讲解Java泛型的优点、方法和相关细节。一、泛型的介绍众所周知,继承是面向对象的三大特性之一。比如我们往集合中添加元素时,add()方法填写的是Object类,Object就是所有的类。父类,这就产生了一个问题——添加的类型不能统一,所以可能会导致类型不统一的问题,在遍历集合取元素的时候报错。例如:我在一个ArrayList集合中添加了一个Person类的对象,却不小心添加了一个Boy类的对象,就会导致如下结果。传统方法在遍历时无法约束添加到集合ArrayList(不安全)的数据类型,需要进行类型转换。如果集合中的数据量很大,会影响效率,大大降低程序的健壮性。因此,设计者针对这个问题引入了泛型!二、使用泛型的好处1、提高程序的健壮性和规范性。针对以上问题,我们在使用泛型的时候,就会很简单。我们只需要在编译完类型后使用泛型指定一个具体的类型,编译器就会自动检测不符合规范的类并抛出错误信息2.编译时,检查添加元素的类型,which提高了安全性3.减少了类型转换的次数,提高了效率不使用泛型时:使用泛型时Type:[Stringperson.show();Person<整数>person2=newPerson<整数>(123);//E->Integerperson.show();}运行结果:classjava.lang.Stringclassjava.lang.Integer三、泛型的常见用法1、定义泛型接口在编写接口时,并没有定义泛型。它默认为Object类。其实这样写是不规范的!如果一个接口的存在是一个规范,那么泛型接口就是规范中的规范interfaceIm{voidhi(Rr);voidhello(Rr1,Rr2,Uu1,Uu2);默认R方法(Uu){返回null;}}在上面的泛型接口中,已经规定必须传入U类和R类的对象,所以当我们传入其他类的对象时,就会报错,如图:"linktype="text"imgurl=""tab="innerlink"rel="nofollow,noindex">4、声明类时,可以使用标识符来表示属性类型、方法返回值类型、参数类型[`classPerson{Es;//可以是属性类型publicPerson(Es){//可以是参数类型this.s=s;}publicEf(){//Canbethereturntypereturns;}publicvoidshow(){System.out.println(s.getClass());//DisplaytheoperationtypeofS}}`](http://mp.weixin.qq.com/s?__biz=MzA3MjMwMzg2Nw==&mid=2247501926&idx=1&sn=bfae8f0369187e45f6b78ee7fe341c06&chksm=9f22ddf2a85554e4b512353067976913167415dca2b12f6b311f1bdaa09a348b2dd6b1af54ea&scene=21#wechat_redirect)可以这样理解:上述的classPerson中的“E”相当于这里的E是一个躯壳占Programmerscancustomizethelatestinterviewquestionsbythemselveswhentheyaredefinedinthefuture,andclickontheJavainterviewlibraryapplettobrushthequestionsonline.[字符串person.show();Person<整数>person2=newPerson<整数>(123);//E->Integerperson.show();}运行结果:classjava.lang.Stringclassjava.lang.Integer三、泛型的常见用法1、定义泛型接口在写接口的时候,泛型是没有定义的。它默认为Object类。其实这样写是不规范的!如果一个接口的存在是一个规范,那么泛型接口就是规范中的规范interfaceIm{voidhi(Rr);voidhello(Rr1,Rr2,Uu1,Uu2);默认R方法(Uu){返回null;}}在上面的泛型接口中,已经规定必须传入U类和R类的对象,所以当我们传入其他类的对象时,就会报错,如图:"linktype="text"imgurl=""tab="innerlink"rel="nofollow,noindex">像这样[`publicstaticvoidmain(String[]args){Personperson1=newPerson("xxxx");//E->Stringperson.show();Personperson2=newPerson(123);//E->Integerperson.show();}运行结果:classjava.lang.Stringclassjava.lang.Integer`](http://mp.weixin.qq.com/s?__biz=MzA3MjMwMzg2Nw==&mid=2247501926&idx=1&sn=bfae8f0369187e45f6b78ee7fe341c06&chksm=9f22dd4e2a85554b512353067976913167415dca2b12f6b311f1bdaa09a348b2dd6b1af54ea&scene=21#wechat_redirect)[Stringperson.show();Personperson2=newPerson(123);//E->Integerperson.show();}运行结果:classjava.lang.Stringclassjava.lang.Integer三、泛型的常见用法1、定义泛型接口在写接口的时候,没有定义泛型。它默认为Object类。其实这样写是不规范的!如果一个接口的存在是一个规范,那么泛型接口就是规范中的规范interfaceIm{voidhi(Rr);voidhello(Rr1,Rr2,Uu1,Uu2);默认R方法(Uu){返回null;}}在上面的泛型接口中,已经规定必须传入U类和R类的对象,所以当我们传入其他类的对象时,就会报错,如图:"linktype="text"imgurl=""tab="innerlink"rel="nofollow,noindex">3.泛型的常用用法[Stringperson.show();Personperson2=newPerson(123);//E->Integerperson.show();}运行结果:classjava.lang.Stringclassjava.lang.Integer三、泛型的常见用法1、定义泛型接口定义泛型,默认为Object类,其实,不规范!如果接口的存在是规范,那么泛型接口就是规范中的规范interfaceIm{voidhi(Rr);voidhello(Rr1,Rr2,Uu1,Uu2);defaultRmethod(Uu){返回空值;}}在上面的泛型接口中,已经规定必须传入U类和R类的对象,所以当我们传入其他类的对象时,就会报错,如图:"linktype="text"imgurl=""tab="innerlink"rel="nofollow,noindex">1.定义通用接口[Stringperson.show();Personperson2=newPerson(123);//E->Integerperson.show();}运行结果:classjava.lang.Stringclassjava.lang.Integer三、泛型的常见用法1、定义泛型接口定义泛型,默认为Object类,其实就是是不规范的!如果接口的存在是规范,那么泛型接口就是规范中的规范interfaceIm{voidhi(Rr);voidhello(Rr1,Rr2,Uu1,Uu2);默认R方法(Uu){returnnull;类对象,那么当我们传入其他类的对象时,就会报错,如图:"linktype="text"imgurl=""tab="innerlink"rel="nofollow,noindex">以前写接口的时候,总是没有定义泛型,默认是Object类。其实这样写是不规范的[String????person.show();????Person?person2?=?new?Person(123);?//E->Integerperson.show();}运行结果:classjava.lang.Stringclassjava.lang.Integer三、泛型的常见用法1、定义泛型接口写接口时,没有定义泛型,它默认是Object类。其实是不规范的!如果一个接口的存在是一个规范,那么通用接口就是规范接口Im在上面的泛型接口中,已经规定必须传入类U和R的对象,所以当我们传入其他类的对象时,会报错,如图:按照规则,我们在实现接口的时候,就必须实现他的所有方法,这时候我们可以将自己指定的类传入在IDEA中重写接口中的方法时,编译器会自动将替换成我们预先指定的类。2.定义一个泛型集合[hm=newHashMap();//K->StringV->Student和下面对应的hm.put("001",newStudent("喜羊羊",21));hm.put("002",newStudent("懒羊羊",32));hm.put("003",newStudent("美丽羊",43));Set>ek=hm.entrySet();Iterator>iterator=ek.iterator();//取出迭代器while(iterator.hasNext()){Map.Entry<字符串,学生>next=iterator.next();System.out.println(next.getKey()+"-"+next.getValue());}HashMap是存储在[K-V]Object中的双列集合,所以在使用泛型时,需要传入两个类型"linktype="text"imgurl=""tab="innerlink"rel="nofollow,noindex">1.使用泛型在HashSet中放入三个学生对象,并输出对象信息[`HashSetstudents=newHashSet();students.add(newStudent("懒羊羊",21));students.add(newStudent("喜羊羊",41));students.add(newStudent("美羊羊",13));for(Studentstudent:students){System.out.println(student);}`](http://mp.weixin.qq.com/s?__biz=MzA3MjMwMzg2Nw==&mid=2247501926&idx=1&sn=bfae8f0369187e45f6b78ee7fe341c06&chksm=9f22ddf2a85554e4b512353067976913167415dca2b12f6b311f1bdaa09a348b2dd6b1af54ea&scene=21#wechat_redirect)[?hm?=?new?HashMap();//?K->?String??V->Student与下面的对应hm.put("001",newStudent("喜羊羊",21));hm.put("002",newStudent("懒羊羊",32));hm.put("003",newStudent("美山羊",43));Set>ek=hm.entrySet();Iterator>iterator=ek.iterator();//取出迭代器while(iterator.hasNext()){Map.Entrynext=iterator.next();System.out.println(next.getKey()+"-"+next.getValue());}HashMap是一个双列集合,以[K-V]的形式存储对象,所以在使用泛型时,两种类型必须被传进去"linktype="text"imgurl=""tab="innerlink"rel="nofollow,noindex">上面提到的泛型中,Student是我预先定义的一个类,把它作为一个泛型放进去对传入对象进行约束,减少遍历时的变换次数,提高效率[hm=newHashMap();//K->StringV->Student对应如下hm.put("001“,新生(”喜羊羊",21));hm.put("002",newStudent("懒羊羊",32));hm.put("003",newStudent("美羊羊",43));设置>ek=hm.entrySet();Iterator>iterator=ek.iterator();//取出迭代器while(iterator.hasNext()){Map.Entrynext=iterator.next();System.out.println(next.getKey()+"-"+next.getValue());}HashMap是一个双列集合,有[K-V]来存储对象,所以使用泛型时,需要传入两个类型给它"linktype="text"imgurl=""tab="innerlink"rel="nofollow,noindex">2.使用泛型方法将三个student对象放入HashMap中,输出对象信息put("001",newStudent("喜羊羊",21));hm.put("002",newStudent("懒羊羊",32));hm.put("003",newStudent("Beautifulsheep",43));Set>ek=hm.entrySet();Iterator>iterator=ek.iterator();//取出迭代器while(迭代器.hasNext()){Map.Entrynext=iterator.next();System.out.println(next.getKey()+"-"+next.getValue());}`][hm=newHashMap();//K->StringV->Student对应到下面hm.put("001",newStudent("喜羊羊",21));hm.put("002",newStudent("懒羊羊",32));hm.put("003",newStudent("BeautifulSheep",43));Set>ek=hm.entrySet();Iterator>iterator=ek.iterator();//取出迭代器while(iterator.hasNext()){Map.Entrynext=iterator.下一个();System.out.println(next.getKey()+"-"+next.getValue());}HashMap是一个两列的集合,在[K-V]中存储对象,所以在使用泛型时要传入两种类型"linktype="text"imgurl=""tab="innerlink"rel="nofollow,noindex">HashMap是一个两列的集合,以[K-V]的形式存储对象,所以在使用泛型时,必须有两个类型传入其中。我们都知道,在使用迭代器遍历HashMap时,首先要通过entrySet()取出键值对,然后通过变换获取对应的类,从而获取对象信息。使用泛型定义时[K-V]指定要检索的键值对类型,省去了转换的步骤,程序变得简单高效。最新面试题整理,点击Java面试库小程序在线刷题。4.泛型使用细节1.<>中的类型规范2.继承体现在为泛型指定一个具体的类型,可以传入类型或其子类类型Pap=newP(newA());Pap1=newP(newB());//AsubclassclassA{}classBextendsA{}3.简写Pap=newP(newA());五、自定义泛型1、自定义方法使用类声明的泛型类型。当形参列表传入的数据类型与泛型类型不一致时,会报错,体现规范publicstaticvoidmain(String[]args){Uu=newU<>();u.hi("你好",1.0);//X->StringY->Double}classU{publicvoidhi(Xx,Yy){}//使用类声明的泛型类型}2.自定义泛型方法publicstaticvoidmain(String[]args){Uu=newU<>();u.m1("xx",22);//调用方法时,编译器会判断传入参数的类型,自动装箱}classU{publicvoidm1(Xx,Yy){}//customgenericmethod}这里的autoboxing很有意思,自动在三种类型中匹配当前输入的数据不需要考虑类型的先后顺序,如图3。注意事项①泛型数组不能初始化,因为数组无法确定new中A的类型,也无法在内存中开辟空间错误的写法:A[]a=newA[];②静态方法不能使用类定义的泛型,因为静态成员与类有关。加载类时,尚未创建对象。因此,如果静态方法和静态属性使用了泛型类型,JVM就无法完成初始化。欢迎关注我的公众号:敲代码的老贾,回复“领取”送《Java面试》信息,阿里、腾讯、字节、美团、饿了么等大厂