第10章抽象类和接口10.1引言10.2抽象类10.3日历类Calendar和公历类GregorianCanlendar10.4接口10.5将基本数据类型值处理为对象10.6基本类型和包装类之间的自动转换10.1引言抽象类:将父类设计得非常抽象,让它包含所有子类的共同属性、方法,以至于它没有具体的实例。接口:实现多重继承10.2抽象类存在意义–抽象类是类层次中较高层次的概括,抽象类的作用是让其他类来继承它的抽象化的特征–抽象类中可以包括被它的所有子类共享的公共行为–抽象类中可以包括被它的所有子类共享的公共属性–在程序中不能用抽象类作为模板来创建对象;–在用户生成实例时强迫用户生成更具体的实例,保证代码的安全性抽象类的格式abstractclass类名{…}抽象方法的语法形式为abstractreturnTypemethodName(...);抽象方法的优点–隐藏具体的细节信息,所有的子类使用的都是相同的方法头,其中包含了调用该方法时需要了解的全部信息–强迫子类完成指定的行为,规定其子类需要用到的“标准”行为–通用程序设计(一般程序设计)例1问:抽象类GeometricObject中的抽象方法可否删除?各种图形都需要实现绘图方法,可在抽象父类中声明一个draw抽象方法abstractclassGraphicObject{intx,y;voidmoveTo(intX,intY){...}abstractvoiddraw();}然后在每一个子类中重写draw方法,例如:classCircleextendsGraphicObject{voiddraw(){...}}classRectangleextendsGraphicObject{voiddraw(){...}}publicclassTest{publicstaticvoidmain(…){GraphicObjectob1=Cirlce();GraphicObjectob2=Cirlce();ob1.draw();ob2.draw();}}例2将所有图形的公共属性及方法抽象到抽象类Shape。再将2D及3D对象的特性分别抽取出来,形成两个抽象类TwoDimensionalShape及ThreeDimensionalShape–2D图形包括Circles、Triangles、Rectangles和Squares–3D图形包括Cube、Sphere、或Tetrahedron–在UML中,抽象类的类名为斜体,以与具体类相区别ShapeCircleTriangleRectangleSquareTwoDimensionalShapeThreeDimensionalShapeCubeSphereTetrahedron例3LoanLeaseMortgageHouseLoanCarLoan贷款(Loan)分为许多种类,如租借(Lease)、抵押(Mortgage)、房屋贷款(HouseLoan)、汽车贷款(CarLoan)等将Loan声明为抽象类,并指定所有的子类对象都应具有的行为,如计算月还款值(calculateMonthlyPayment),还款(makePayment),取得客户信息(getClientInfo),其中前两个因贷款种类不同计算方法也不同,可声明为抽象方法,Loan的所有子类都必须对这两个抽象方法进行重写publicabstractclassLoan{publicabstractfloatcalculateMonthlyPayment();publicabstractvoidmakePayment(floatamount);publicClientgetClientInfo(){}}例4注意:–1抽象类前需加修饰符abstract–2不能使用new方法进行实例化,故,抽象类必须被继承–3抽象类可包含常规类能够包含的任何东西,例如构造方法等非抽象方法,其构造方法在子类的构造方法中调用–4没有抽象方法的类也可被声明为抽象类–5包含抽象方法的类必须声明为抽象类–6若子类没有实现父类的全部抽象方法,它也必须声明为抽象类–7抽象方法必须是非静态的,子类中的实现也必须是非静态的,否则无法覆盖–8即便父类是具体类,子类也可能是抽象类–9抽象类虽然无法用new实例化,但可以用作数据类型例:抽象类x;抽象类a[5]=new抽象类[5];x=new子类();a[i]=new子类();10.3日历类Calendar和公历类GregorianCanlendar10.4接口1.Java不支持多重继承,是为了使语言本身结构简单,层次清楚,易于管理,更安全可靠,避免冲突。但同时也就限制了语言的功能。2.为了在实际应用中借助多重继承的功能,共享一些公用的常量和一些常用的方法,Java使用接口来弥补。一个类可以实现多个接口,达到多重继承的效果。3.接口可以看作是常量和没有实现的方法的集合。4.接口与抽象类相似,接口中的方法只是做了声明,而没有定义任何具体的操作方法。声明接口的格式修饰符interface接口名{/**常量*//**抽象方法*/}方法自动为publicabstract变量自动为publicstaticfinalpublicinterfaceComparable{publicintcompareTo(Object);}例如packagejava.langpublicfinalclassStringextendsObjectimplementsSerializable,Comparable,CharSequence{publicintcompareTo(StringanotherString){……}}publicclassDateextendsObjectimplementsSerializable,Cloneable,Comparable{publicintcompareTo(DateanotherDate){……}}类java.lang.String和Java.util.Date都实现了Comparable接口右边的表达式都成立sinstanceofStringsinstanceofObjectsinstanceofComparables.compareTo(“china”)返回0“china”.compareTo(s)返回0“china”.compareTo(“japan”)返回-7publicclassMax{publicstaticComparablemax(Comparableo1,Comparableo2){if(o1.compareTo(o2)0)returno1;elsereturno2;}}应用:例如StringmaxString=(String)Max.max(s,”japan”)若Strings=“china”;应用例如P277的图a和图b问:为什么说图a更鲁棒?接口–与抽象类一样都是定义多个类的共同属性–使抽象的概念更深入了一层,是一个“纯”抽象类,它只提供一种形式,并不提供实现–允许创建者规定方法的基本形式:方法名、参数列表以及返回类型,但不规定方法主体。方法自动为publicabstract–也可以包含基本数据类型的数据成员,但它们都自动为publicstaticfinal接口允许我们在看起来不相干的对象之间定义共同行为接口的作用–是面向对象的一个重要机制–实现多继承,同时免除C++中的多继承那样的复杂性–建立类和类之间的“协议”把类根据其实现的功能来分别代表,而不必顾虑它所在的类继承层次;这样可以最大限度地利用动态绑定,隐藏实现细节实现不同类之间的常量共享接口的语法–声明格式为[public]interface接口名称[extends父接口名]{…//方法的原型声明或静态常量}–接口的数据成员一定要赋初值,且此值将不能再更改,允许省略publicstaticfinal关键字–接口中的方法必须是“抽象方法”,不能有方法体,允许省略publicabstract关键字接口也可以继承接口的实现接口的实现–接口不能用new运算符直接产生对象,必须利用其特性设计新的类,再用新类来创建对象–利用接口设计类的过程,称为接口的实现,使用implements关键字–语法如下publicclass类名称implements接口名称{/*Bodiesfortheinterfacemethods*//*Owndataandmethods.*/}必须实现接口中的所有方法实现接口的方法必须声明成public例1声明一个接口Shape2D,可利用它来实现二维的几何形状类Circle和Rectangle–把计算面积的方法声明在接口里–pi值是常量,把它声明在接口的数据成员里interfaceShape2D{//声明Shape2D接口finaldoublepi=3.14;//数据成员一定要初始化publicabstractdoublearea();//抽象方法}–在接口的声明中,允许省略一些关键字,也可声明如下interfaceShape2D{doublepi=3.14;doublearea();}例2classCircleimplementsShape2D{doubleradius;publicCircle(doubler){radius=r;}publicdoublearea(){return(pi*radius*radius);}}classRectangleimplementsShape2D{intwidth,height;publicRectangle(intw,inth){width=w;height=h;}publicdoublearea(){return(width*height);}}声明Circle与Rectangle两个类实现Shape2D接口测试类publicclassInterfaceTester{publicstaticvoidmain(Stringargs[]){Rectanglerect=newRectangle(5,6);System.out.println(Areaofrect=+rect.area());Circlecir=newCircle(2.0);System.out.println(Areaofcir=+cir.area());}}运行结果Areaofrect=30.0Areaofcir=12.56声明接口类型的变量,并用它来访问对象publicclassVariableTester{publicstaticvoidmain(String[]args){Shape2Dvar1,var2;var1=newRectangle(5,6);System.out.println(Areaofvar1=+var1.area());var2=newCircle(2.0);System.out.println(Areaofvar2=+var2.area());}}输出结果Areaofvar1=30.0Areaofvar2=12.56多重继承–Java的设计以简单实用为导向,不允许一个类有多个父类–但允许一个类可以实现多个接口,通过这种机制可实现多重继承–一个类实现多个接口的语法如下[类修饰符]class类名称implements接口1,接口2,…{……}Car类可以实现接口Insurable,Drivable,SellablepublicclassCarimplementsInsurable,Drivable,Sellable{....}例3声明Circle类实现接口Shape2D和Color–Shape2D具有pi与area()方法,用来计算面积–Color则具有setColor方法,可用来赋值颜色–通过实现这两个接口,Circle类得以同时拥有这两个接口的成员,达到了多重继承的目的interfaceShape2D{//声明Shape2D接口finaldoublepi=3.14;//数据