1987WEB视界-分享互联网热点话题和事件

您现在的位置是:首页 > WEB开发 > 正文

WEB开发

day29--Java泛型02

1987web2024-03-27WEB开发40
Java泛型025.自定义泛型

Java泛型02

5.自定义泛型

5.1自定义泛型类

基本语法:

class类名<T,R...>{//…表示可以有多个泛型成员}

注意细节:

普通成员可以使用泛型(属性、方法)使用泛型的数组不能初始化静态方法中不能使用类的泛型泛型类的类型,是在创建类的对象时确定的(因为创建对象时,需要指定确定类型)如果在创建对象时没有指定类型,默认为Object

例子:

// Tiger后面有泛型,所以我们把 Tiger称为自定义泛型类classTiger<T,R,M>{// T,R,M是泛型的标识符,一般是单个的大写字母;泛型的标识符可以有多个Stringname;R r;// 普通成员可以使用泛型(属性、方法),这里是属性使用泛型M m;T t;// 使用泛型的数组不能初始化,因为数组在new的时候不能确定T的类型,就无法在内存开辟空间T[]ts;publicTiger(Stringname){this.name=name;}publicTiger(R r,M m,T t){// 构造器使用泛型this.r=r;this.m=m;this.t=t;}//因为静态是和类相关的,在来加载的时候,对象还没有创建//所以如果静态方法和静态属性使用到泛型,JVM就无法完成初始化//因此静态方法和静态属性不能使用泛型// static R r2;// public static void m1(M m){//// }publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicR getR(){returnr;}publicvoidsetR(R r){// 方法使用泛型this.r=r;}publicM getM(){// 返回类型 使用泛型returnm;}publicvoidsetM(M m){this.m=m;}publicT getT(){returnt;}publicvoidsetT(T t){this.t=t;}@OverridepublicStringtoString(){return"Tiger{"+"name="+name+\+", r="+r+", m="+m+", t="+t+", ts="+Arrays.toString(ts)+};}}

练习:说明自定义泛型代码是否正确,并说明原因

packageli.generic.customgeneric;importjava.util.Arrays;publicclassCustomGeneric_{publicstaticvoidmain(String[]args){//T=Double , R=String , M=IntegerTiger<Double,String,Integer>g=newTiger<>("john");//okg.setT(10.9);//ok// g.setT("yy");//错误,类型不对System.out.println(g);//这里没有指定泛型类型,全部默认为Object类型//T=Object , R=Object , M=ObjectTigerg2=newTiger("join~~");g2.setT("yy");//ok,因为T为Object类型,“yy”为String类型,是Object的子类System.out.println("g2="+g2);}}

5.2自定义泛型接口

基本语法:

interface接口名<T,R...>{}

注意细节:

接口中,静态成员不能使用泛型(这个和泛型类的规定一样)泛型接口的类型,在继承接口或者实现接口时确定没有指定类型,就默认为Object类

例子:

packageli.generic.customgeneric;publicclassCustomInterfaceGeneric{publicstaticvoidmain(String[]args){}}interfaceIUsb<U,R>{//U name; //这里的接口属性默认前面加上了static final,接口中,静态成员不能使用泛型//普通方法中,可以使用接口泛型R get(U u);voidhi(R r);voidrun(R r1,R r2,U u1,U u2);//在jdk8中,可以在接口中使用默认方法,也是可以使用泛型的defaultR method(U u){returnnull;}}// 在继承接口时,指定泛型接口的类型interfaceIAextendsIUsb<String,Double>{}//当我们去实现IA接口时,因为IA在继承IUsb接口时,指定了U为String类型,R为 Double类型//因此,在实现IUsb方法的时候,使用String替换U,使用Double替换RclassAAimplementsIA{@OverridepublicDoubleget(Strings){returnnull;}@Overridepublicvoidhi(DoubleaDouble){}@Overridepublicvoidrun(Doubler1,Doubler2,Stringu1,Stringu2){}}//实现接口时,直接指定泛型接口的类型//给U指定了Integer,给R指定了Float//所以当我们实现IUsb方法时,会使用Integer替换U,使用Float替换RclassBBimplementsIUsb<Integer,Float>{@OverridepublicFloatget(Integerinteger){returnnull;}@Overridepublicvoidhi(FloataFloat){}@Overridepublicvoidrun(Floatr1,Floatr2,Integeru1,Integeru2){}}//没有指定类型,则默认为ObjectclassCCimplementsIUsb{//等价于 class CC implements IUsb{@OverridepublicObjectget(Objecto){returnnull;}@Overridepublicvoidhi(Objecto){}@Overridepublicvoidrun(Objectr1,Objectr2,Objectu1,Objectu2){}}

5.3自定义泛型方法

基本语法:

修饰符<T,R...>返回类型方法名(参数列表){}

注意细节:

泛型方法,可以定义在普通类中,也可以定义在泛型类中当泛型方法被调用时,类型会确定public void eat(E e){},修饰符后面没有 则eat方法不是泛型方法,只是使用了泛型

例子:

packageli.generic.customgeneric;importjava.util.ArrayList;publicclassCustomMethodGeneric{publicstaticvoidmain(String[]args){Carcar=newCar();car.fly("宝马",100);//当调用方法时,传入参数,编译器就会确定类型// class java.lang.String//class java.lang.IntegerSystem.out.println("==========");car.fly(300,100.7);//当调用方法时,传入参数,编译器就会确定类型//class java.lang.Integer//class java.lang.DoubleSystem.out.println("==========");//fish的T=String,R=ArrayListFish<String,ArrayList>fish=newFish<>();fish.hello(newArrayList(),11.3f);//class java.util.ArrayList//class java.lang.Float}}//泛型方法,可以定义在普通的类中,也可以定义在泛型类中classCar{//普通类publicvoidrun(){//普通方法}//就是泛型,是提供给fly方法使用的public<T,R>voidfly(T t,R r){//泛型方法System.out.println(t.getClass());System.out.println(r.getClass());}}classFish<T,R>{//泛型类publicvoidrun(){//普通方法}public<U,M>voideat(U u,M m){//泛型方法}//说明:下面的hi方法不是泛型方法,因为修饰符后面没有表示符//是hi方法使用了类声明的泛型publicvoidhi(T t){}//泛型方法可以使用类声明的泛型,也可以使用自己声明的泛型public<K>voidhello(R r,K k){//R是类声明的标识符,K则是方法自己声明的标识符System.out.println(r.getClass());System.out.println(k.getClass());}}

5.4泛型方法练习

下面代码是否正确,如果有错误,修改正确,并说明输出什么?

packageli.generic.customgeneric;publicclassCustomMethodGenericExercise{publicstaticvoidmain(String[]args){Apple<String,Integer,Double>apple=newApple<>();//okapple.fly(10);//ok 10会被自动装箱,输出Integerapple.fly(newDog());//ok 输出Dog}}classApple<T,R,M>{public<E>voidfly(E e){//泛型方法System.out.println(e.getClass().getSimpleName());}// public void eat(U u) {}//错误,因为U没有声明publicvoidrun(M m){}}classDog{}

6.泛型继承和通配

泛型的继承和通配符说明:

泛型不具备继承性

List

:支持任意泛型类型

:支持A类以及A类的子类,规定了泛型的上限