JAVA基础java基础4(JAVA继承JAVA多态抽象类接
JAVA继承
继承是由子对象完全继承父对象的数据和操作,is的关系。被继承的类被称为父类(superclass),也叫基类、超类。继承后的类称为子类(subclass),也叫派生类。
java支持单继承,使用关键字extends
语法:子类extends父类
复制
例:定义一个Animal类,再创建一个Dog类,继承Animal类。classDogextendsAnimal{。。。。。}publicclassPerson{publicStringname;publicStringsex;protectedintage;publicPerson(){super();}publicPerson(Stringname,Stringsex,intage){super();this。namename;this。sexsex;this。ageage;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){this。namename;}publicStringgetSex(){returnsex;}publicvoidsetSex(Stringsex){this。sexsex;}publicintgetAge(){returnage;}publicvoidsetAge(intage){this。ageage;}}
复制publicclassEmployeeextendsPerson{privateStringcomName;publicEmployee(){super();TODOAutogeneratedconstructorstub}publicEmployee(Stringname,Stringsex,intage,StringcomName){super。namename;super。sexsex;super。ageage;this。comNamecomName;}publicEmployee(StringcomName){super();this。comNamecomName;}publicStringgetComName(){returncomName;}publicvoidsetComName(StringcomName){this。comNamecomName;}}
复制子类若要引用父类的同名变量。要用super关键字,即super。变量名。子类若要引用父类的构造函数,通过super()调用。this关键字:
表示当前对象,可以用于:1。引用自身对象的成员变量this。age;
2。引用自身对象的成员方法this。display();
3。调用自身的构造方法this(Jack,Male,10);super关键字
super表示使用它的类的父类。super可用于:1。引用父类对象的成员变量super。age;
2。引用父类对象的成员方法super。display();
3。调用父类的构造方法super(Jack,Male,10);
在java中,每一个类都默认具有null、this、super三个域,因此在任何类中都可以直接引用。
注意:1。构造方法使用this或super时,必须位于方法体的第一条。2。this不能用于static3。构造方法不能被继承4。当通过子类不含参数的构造函数创建子类对象时,先执行父类不含参数的构造函数,再执行子类不含参数的构造函数。5。如果定义一个;类,没有调用extends,则它的父类是:java。lang。Object形参和实参定义方法的参数是形式参数调用方法的参数是实在参数调用方法时要求参数个数相同,类型兼容对象的比较和equals()比较两个基本类型变量的值是否相等比较两个引用类型的值即内存地址是否相等,即是否指向同一对象。equals()比较两个对象的内容是否相等JAVA多态(polymorphism)
多态是指同一个方法可作用于不同的对象,从而执行不同的方法代码并获得不同的结果。
1。多态是继封装、继承之后,面向对象的第三大特性。
2。多态现实意义理解:
现实事物经常会体现出多种形态,如学生,学生是人的一种,则一个具体的同学张三既是学生也是人,即出现两态。Java作为面向对象的语言,同样可以描述一个事物的多种形态。如Student类继承了Person类,一个Student的对象便既是Student,又是Person。
3。多态体现为父类引用变量可以指向子类对象。
4。前提条件:必须有子父类关系。
注意:在使用多态后的父类引用变量调用方法时,会调用子类重写后的方法。
5。多态的定义与使用格式定义格式:父类类型变量名new子类类型();
复制多态中成员的特点
1。多态成员变量:编译运行看左边FufnewZi();System。out。println(f。num);f是Fu中的值,只能取到父中的值
复制
2。多态成员方法:编译看左边,运行看右边Fuf1newZi();System。out。println(f1。show());f1的门面类型是Fu,但实际类型是Zi,所以调用的是重写后的方法。
复制
java支持两种多态:动态多态和静态多态。静态多态性:在编译时,就可以被系统识别,也称为编译时多态、静态联编、静绑定。方法重载(overload)采用的是静态联编的方法实现。动态多态性:在编译时不能被系统识别,而是在运行时才能被系统识别,也称为运行时多态,也称动态联编,也称动绑定。方法覆盖(override)〔也叫方法重写〕、抽象方法和接口采用动态联编的方法实现。方法重载:
在同一个类中,方法名相同,参数列表不同,与返回值无关。publicclassMethodOverload{publicstaticvoidmain(Stringargs〔〕){inta51,b98,c8,d191;doubleu25。1,v29。8,x3。1,y89。98;System。out。println(51、98、8、191四数的最大值是:max(a,b,c,d));System。out。println(25。1、29。8、3。1、89。98四数的最大值是:max(u,v,x,y));}staticintmax(inta,intb,intc,intd){intx,y;xab?a:b;ycd?c:d;returnxy?x:y;}staticdoublemax(doublea,doubleb,doublec,doubled){doublex,y;xab?a:b;ycd?c:d;returnxy?x:y;}如果一个类中有两个同名方法,其参数列表完全一样,仅仅返回值类型不同,则编译时会产生错误staticdoublemax(inta,intb,intc,intd){intx,y;xab?a:b;ycd?c:d;returnxy?x:y;}}
复制
方法重写(方法覆盖):
在子类继承父类的关系中,子类的方法名和父类的方法名相同,参数列表相同,返回值类型相同。classSup{publicintx,y;Sup(inta,intb){xa;yb;}publicvoiddisplay(){intz;zxy;System。out。println(addz);}}classSubextendsSup{Sub(inta,intb){super(a,b);}publicvoiddisplay(){intz;zxy;System。out。println(productz);}}diaplay()在编译时不能被系统识别,而是在运行时才被系统识别,也称为运行时多态,也称为动态联编,也称为动绑定。publicclassResultDemoextendsSub{ResultDemo(intx,inty){super(x,y);}publicstaticvoidmain(Stringargs〔〕){Supnum1newSup(7,14);Subnum2newSub(7,14);ResultDemonum3newResultDemo(7,14);num1。display();num2。display();num3。display();num1num2;num1。display();num1num3;num1。display();}}
复制
多态有三个条件:
1。有继承关系2。方法重写3。父类的声明指向子类的引用
例1:classAnimal{intage10;publicvoidshout(){System。out。println(叫了一声);}}classDogextendsAnimal{intage28;publicvoidshout(){System。out。println(汪汪汪);}publicvoidgnawBone(){System。out。println(我在啃骨头);}}classCatextendsAnimal{intage18;publicvoidshout(){System。out。println(喵喵喵);}}
复制publicclassTestPolym{publicstaticvoidmain(String〔〕args){AnimalanimalnewDog();向上可以自动转型System。out。println(animal。age);属性调用时,仍然是基类的属性,属性没有多态!animalCry(newDog());传的具体是哪一个类就调用哪一个类的方法,大大提高了程序的可扩展性。如果没有多态,这里需要写很多的重载方法,如果增加一种动物,就需要重载一种动物的喊叫方法,非常麻烦。有了多态,只需要增加这个类继承Animal基类就可以了。animalCry(newCat());Dogdog(Dog)animal;编写程序时,如果想要调用运行时类型的方法,只能进行类型转换,不然通不过编译器的检查。dog。gnawBone();}}
复制多态的转型:
分为向上转型和向下转型。向上转型:多态本身就是向上转型的过程。
格式:父类类型变量名new子类类型
复制
适用场景:当不需要面对子类类型时,通过提高扩展性,或者使用父类的功能就能完成相应的操作。publicclassAnimal{publicvoideat(){System。out。println(animaleatting。。。);}}publicclassCatextendsAnimal{publicvoideat(){System。out。println(猫吃鱼);}}publicclassDogextendsAnimal{publicvoideat(){System。out。println(狗吃骨头);}publicvoidrun(){System。out。println(我会跑);}}publicclassMain{publicstaticvoidmain(String〔〕args){AnimalanimalnewDog();向上转型animal。eat();}}输出:狗吃骨头
复制
上面的就是向上转型,AnimalanimalnewDog();就是将子类对象Dog转化为父类对象Animal。这时animal这个引用调用的方法是子类方法。
向上转型注意点:
1。向上转型时,子类单独定义的方法会丢失,比如上面的Dog类中定义的run方法,当animal引用指向Dog类实例是访问不到run方法的,animal。run();会报错。2。子类不能指向父类对象。Dogd(Dog)newAnimal这样是不行的。
向上转型好处:1。减少重复代码2。提高系统扩展性向下转型:一个已经向上转型的子类对象可以使用强制类型转换的格式,将父类对象转为子类对象。
格式:子类类型变量名(子类类型)父类类型的变量;
复制
适用场景:当要使用子类特有功能时。
以上面的例子来说:还是上面的animal和catdogAnimalanewCat();Catc((Cat)a);c。eat();输出我吃鱼Dogd((Dog)a);d。eat();报错:java。lang。ClassCastException:com。wr。animal。Catcannotbecasttocom。wr。animal。DogAnimala1newAnimal();Catc1((Cat)a1);c1。eat();报错:java。lang。ClassCastException:com。wr。animal。Animalcannotbecasttocom。wr。animal。Cat
复制
为什么第一段代码不报错呢,因为a本身就是Cat对象,所以当然可以转型为Cat,因为是Cat所以不能转为Dog。而a1是Anmail对象,它不能向下转型Wie任何子类对象。比如发现一个古生物化石,知道它是一种动物,但你不能直接说他是猫或者他是狗。
向下转型注意点:
1。向下转型的前提是父类对象指向的是子类对象(也就是说,在向下转型之前,它得先向上转型)2。向下转型只能转型为本类对象(猫是不能变成狗的)。instanceof关键字
有一个场景:江苏人包含:淮安人、盐城人、扬州人。淮安人、盐城人、扬州人一定都是江苏人;反过来,江苏人不一定都是淮安人。父类和子类的对象之间转换:java允许在父类和子类的对象之间进行转换:1。自动转换2。强制类型转换
子类和父类之间存在着isa的关系,所以子类转换为父类对象时,是自动转换。当父类对象转换为子类对象时,必须要强制类型转换。强制类型转换的格式:if(父类对象名instanceof子类名){子类对象名(子类名)父类对象名;}else{}
复制Fuf1newZi();Fuf2newSon();if(f1instanceofZi){System。out。println(f1是Zi的类型);}else{System。out。println(f1是Son的类型);}
复制final关键字
用来修饰变量、方法、类。修饰变量:变量一旦初始化就不能改变,相当于定义了常量finalintx3;修饰方法:final方法在子类不能被重写(覆盖)finalvoideat(){}修饰类:final类不能被任何类继承(最终类)finalclassPerson{}抽象类
抽取子类共有的属性和方法。
设计S和S1的时候发现S和S1有共有的属性和方法就将S和S1的共有属性和方法抽象出来成为一个新的类叫做抽象类abstract修饰的类就是抽象类抽象类:
1、抽象类不能实例化,只能通过之类实例化2、抽象类中可以有抽象方法,可以有实例方法,可以有实例变量实例方法:有方法的声明有方法的实现抽象方法:只有方法的声明没有方法的实现,不能存在于普通类,就是用来被重写3、如果一个类继承了一个抽象类必须重写所有抽象父类中所有的抽象方法,否则这个也是抽象类4、抽象类是重构的结果
例abstractclassAnimal{abstractvoidshout();抽象方法没有方法体!}classDogextendsAnimal{voidshout(){必须重写父类的抽象方法否则编译通不过System。out。println(汪汪汪!);}}
复制接口
怎么理解?接口其实就是比抽象类还抽象的抽象类,实现规范和具体实现的分离。接口就是规范,定义的是一组规则,体现了现实世界中如果你是则必须能的的思想。如果你是好人,则必须能干掉坏人。接口的本质是契约,就想现实中的法律一样,制定好后大家就要遵守。开发往往就是面向接口编程。
接口(interface)是一组方法集,接口中包含的方法都是抽象方法,定义方法体的任务留给实现该接口的类去完成。接口的要点:
1。接口是java中的一种复合数据类型,使用interface关键字来定义的。2。接口是一种特殊的类,一种特殊的抽象类。3。接口中所有的方法都默认是publicabstract的,并且只有方法头和参数列表,没有方法体。4。接口中所有的变量都默认是publicstaticfinal的。5。接口中没有构造方法。6。接口可以继承,并且可以多继承。7。一个类可以实现多个接口。
注意点:
1。一个类可以继承一个类的同时实现多个接口,必须重写父类们的所有的抽象方法;2。接口不能实例化,只能通过子类实例化。普通类、抽象类、接口的区别?普通类:class修饰的有成员变量、成员方法、构造函数抽象类:abstractclass修饰有成员变量、成员方法、抽象方法、构造函数(只能被子类调用)接口:interface修饰只有publicfinalstatic修饰的变量和publicabstract修饰的方法接口和抽象类的区别:
1、抽象类和接口都不能直接实例化,如果要实例化,只能通过子类进行实例化。2、抽象类要被子类继承,接口要被类实现。3、接口所有的方法都是抽象方法,抽象类中可以可以有抽象方法也可以有实例方法。4、接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。5、抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,一个实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。6、抽象方法只能声明,不能实现,接口是设计的结果,抽象类是重构的结果7、抽象类里可以没有抽象方法8、抽象方法要被实现,所以不能是静态的,也不能是私有的。9、接口可继承接口,并可多实现接口,但抽象类只能单根继定义接口:〔public〕〔interface〕接口名称〔extends父接口名列表〕{静态常量〔public〕〔static〕〔final〕数据类型变量名常量名;抽象方法〔public〕〔abstract〕〔native〕返回值类型方法名(参数列表);}
复制
接口可以继承,而且可以多继承interfaceIA{。。}interfaceIB{。。}interfaceIB{。。}interfaceIDextendsIA,IB,IC{。。}
复制实现接口:〔修饰符〕class类名〔extends父类名〕〔implements接口A,接口B,。。。〕{类的成员变量和成员方法;为接口A中的所有方法编写方法体,实现接口A;为接口A中的所有方法编写方法体,实现接口B;。。。}
复制〔修饰符〕classAimplementsIA{。。。}〔修饰符〕classBextendsAimplementsIB,IC{。。}
复制interfaceIExample{voidmethod1();voidmethod2();}abstractclassExample1implementsIExample{publicvoidmethod1(){。。。。}}因为只实现了一个方法,所以类Example1需要定义成抽象类。
复制
接口代码:publicinterfaceFlyer{publicvoidtakeOff();publicvoidland();publicvoidfly();}publicclassBirdextendsAnimalimplementsFlyer{publicvoidtakeOff()〔。。。。〕publicvoidland(){。。。。}publicvoidfly(){。。。。}publicvoidbuildNest(){。。。。}publicvoidlayEggs(){。。。。}publicvoideat(){。。。。}}