通常我们在看一些源码时,发现全是T、?,晕乎乎的:sob:。于是,把泛型掌握好十分重要! 什么是泛型Java泛型(generics)是JDK5中引入的一个新特性,泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。 泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。 泛型有什么好处?写个例子一目了然: 我们要封装一个消息响应类:publicclassResultimplementsSerializable{响应码I是否成功B返回体数据UpublicResult(Integercode,Booleansuccess,Useruser){this。this。this。}OverridepublicStringtoString(){returnResult{codecode,successsuccess,useruser};}publicstaticvoidmain(String〔〕args){UserusernewUser(1,Tony);ResultresultnewResult(200,true,user);System。out。println(result);}}classUserimplementsSerializable{ISpublicUser(Integerid,Stringname){this。this。}OverridepublicStringtoString(){returnUser{idid,namename};}}Result{code200,successtrue,userUser{id1,nameTony}}进程已结束,退出代码0 呼这样这个反应体就可以返回请求状态和用户信息了。可现在需求又需要返回关于手机的信息,那我们又得封装一个能返回手机信息的响应类了。。。到后面还有衣服、鞋子。。。那不得累死?这时候泛型登场了:publicclassResultTimplementsSerializable{响应码I是否成功B返回体数据TpublicResult(Integercode,Booleansuccess,Tdata){this。this。this。}OverridepublicStringtoString(){returnResult{codecode,successsuccess,datadata};}publicstaticvoidmain(String〔〕args){UserusernewUser(1,Tony);ResultUserresultUsernewResult(200,true,user);System。out。println(resultUser);PhonephonenewPhone(999。99,Yellow);ResultPhoneresultPhonenewResult(200,true,phone);System。out。println(resultPhone);}}classUserimplementsSerializable{ISpublicUser(Integerid,Stringname){this。this。}OverridepublicStringtoString(){returnUser{idid,namename};}}classPhoneimplementsSerializable{DSOverridepublicStringtoString(){returnPhone{priceprice,colorcolor};}publicPhone(Doubleprice,Stringcolor){this。this。}}Result{code200,successtrue,dataUser{id1,nameTony}}Result{code200,successtrue,dataPhone{price999。99,colorYellow}}进程已结束,退出代码0 可见,利用泛型,可以统一标识需要返回的实体类。不管你来什么类,我都可以给你塞进去! 第一次接触可能看不太明白,下面就详细讲解泛型方法 你可以写一个泛型方法,该方法在调用时可以接收不同类型的参数。根据传递给泛型方法的参数类型,编译器适当地处理每一个方法调用。语法规则所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前 比如说这是一个用来打印数组的泛型方法:privatestaticEvoidprintArray(E〔〕inputArray)每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。 比如这个方法privatestaticE,TvoidprintArray(E〔〕inputArray,Tdata)类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型,不能是原始类型(intdoublechar等)泛型标记符EElement集合元素TTypeJava类KKey键VValue值NNumber数值类型?表示不确定的Java类型 这些标记并不是限定只有对应的类型才能使用,即使你统一使用AZ英文字母的其中一个,编译器也不会报错。之所以又不同的标记符,这是一种约定。在开发中很多规则都是一种约定,它能提高我们代码的可读性,方便团队见的合作开发 写个完整的例子:publicclassTFunction{publicstaticvoidmain(String〔〕args){创建各种类型的数组Integer〔〕intArray{1,2,3,4,5};Double〔〕doubleArray{1。1,2。2,3。3,4。4};Character〔〕charArray{H,E,L,L,O};System。out。println(整型数组元素为:);printArray(intArray);传递一个整型数组System。out。println(双精度型数组元素为:);printArray(doubleArray);传递一个双精度型数组System。out。println(字符型数组元素为:);printArray(charArray);传递一个字符型数组}泛型方法privatestaticEvoidprintArray(E〔〕inputArray){遍历打印数组Arrays。stream(inputArray)。forEach(e{System。out。printf(s,e);});System。out。println();}}泛型类 泛型类的声明与非泛型类几乎相同,唯一的不同在于类名的后面添加了参数声明部分 这边就不举例子了,因为开篇的例子就是封装了一个泛型类,当时不太理解的可以再回去看一下类型通配符? 我们一般可以使用?来承接所有的引用类型,搬运一个菜鸟上的例子:publicclassGenericTest{publicstaticvoidmain(String〔〕args){ListStringnamenewArrayListString();ListIntegeragenewArrayListInteger();ListNumbernumbernewArrayListNumber();name。add(icon);age。add(18);number。add(314);getData(name);getData(age);getData(number);}publicstaticvoidgetData(L?data){System。out。println(data:data。get(0));}}data:icondata:18data:314?extendsT 这是泛型上边界:只有T对象的子类可以被传入 如果是?extendsC,那么只有D和E允许被传入,否则会编译报错 ?superT 这是泛型下边界:只有T对象的父类可以被传入 如果是?superD,那么只有C和A允许被传入,否则会编译报错 T和? 不知道看到这里,有没有疑惑。T和?好像作用差不多啊,有什么区别? 这里解释一下,T一般作为泛型参数,而?是更多是用来一个不确定的引用类型,意会一下吧 T和Object 重头戏!! 知道的Object的同志都了解其是Java的超类(所有对象的父类),不了解的可以去看看我的博客,有做详细的解释。 那么问题就来了,Object好像可以代替泛型的功能啊!所有能用到泛型的地方Object都可以! 其实,在JDK5之前,都是用的Object,但其存在很多的问题,JDK5之后便引入了泛型 Object是所有类的父类,在编码过程中就难免出现类型转化问题,且在编译阶段不会报错,到了运行阶段才暴露问题,大大降低了程序的安全性和健壮性! 举例之前说一些转型的分类:向上转型用父类声明一个子类对象例如:Animal是Cat的父类,在声明时我们这么写:AnimalcatnewCat();向下转型将父类对象强转为其子类实例:AnimalcatnewCat();CatanotherCat(Cat) 所以当我们使用Object作为泛型来使用时,不仅写起来麻烦,还要不停的进行类型转化,还很容易出现问题,很逊的诶 举个例子看看: 利用Object定义了一个数字变量,我们常识将其向下转型为Integer和String。将一个数字转型为字符串是一件荒唐的事情,可编译器并不能察觉这件事,直到程序运行了起来。。。 类型转换异常!!!总结 泛型的出现,当类型转化出现问题的时候,在编译阶段就会暴露出来。解决了Object存在的诸多问题,让代码更加优雅,程序更加安全,更加健壮。 作者:不想起床的小张 链接:https:juejin。cnpost7072703705811779620