《第5章 面向对象编程进阶.ppt》由会员分享,可在线阅读,更多相关《第5章 面向对象编程进阶.ppt(74页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、LOGO第5章面向对象编程进阶主要内容主要内容类的继承类的继承1多态性多态性2静态初始化块静态初始化块3finalfinal修饰符修饰符4面向对象编程的三大特征:封装、继承继承和多态多态。主要内容5抽象类抽象类6接口接口7内部类内部类8匿名类匿名类5.1类的继承人是哺乳动物,因为人都具有哺乳动物的所有特征,但哺乳动物却不一定是人。哺乳动物类和人类之间就存在继承关系(IS-A)。mammalsdogscatshumanslionstigersleopards5.1类的继承继承是面向对象三大特征之一,也是实现软件复用的重要手段。继承的特点继承的特点通过继承,在已有类型基础之上进行扩充或改造,得到新
2、的数据类型。已有的类型称为父类或超类。得到的新数据类型,称为子类或派生类类的继承提高了程序代码的重用性和可扩充性,缩短了软件开发的周期。5.1类的继承继承的分类单继承-子类只能有一个直接父类多重继承-子类可以有多个直接父类类A类B类C类A类BJava不支持多重继承不支持多重继承5.1类的继承子类继承父类的语法格式修饰符class子类名extends父类名/子类代码部分例5.1编写程序示范子类继承父类的特点。publicclassAnimalpublicdoubleweight;publicvoideat()System.out.println(动物在吃东西);扩展(继承)5.1类的继承publ
3、icclassDogextendsAnimalpublicvoidsay()System.out.pringln(“狗叫:汪汪汪”);publicstaticvoidmain(Stringargs)Dogd=newDog();d.weight=150;d.eat();d.say();Dog类中没有定义weight属性和eat方法,是从父类Animal中继承下来,并且访问权限没有发生变化如果定义Java类时并未显示指定这个类的直接父类,则这个类默认扩展java.lang.Object类5.1类的继承 重写父类的方法重写父类的方法子类扩展父类-总是以父类为基础,额外增加新的属性和方法。但有一种情况
4、例外:子类需要重写父类的方法。例5.2子类重写父类的方法publicclassBirdpublicvoidfly()System.out.println(我在飞);5.1类的继承publicclassOstrichextendsBird/重写Bird类的fly方法-方法覆盖(方法覆盖(override)publicvoidfly()System.out.println(我只能在地上奔跑);publicstaticvoidmain(Stringargs)Ostrichos=newOstrich();os.fly();/调用的是Bird的fly还是Ostrich的fly?重写父类方法5.1类的继承
5、方法重写时要遵循的规则:“两同两小一大两同两小一大”规则规则“两同”即方法名相同,形参列表相同;“两小”指的是子类方法返回值类型应比父类方法返回值类型更小或相等,子类方法声明抛出的异常类应比父类方法声明抛出的异常类更小或相等;“一大”指的子类方法的访问权限应比父类方法更大或相等;覆盖方法和被覆盖方法要么都是类方法,要么都是实例方法,不能一个是类方法,一个是实例方法。5.1类的继承方法重写和方法重载的区别覆盖是子类和父类之间的关系;而重载是同一类内部多个方法之间的关系。覆盖一般是两个方法间的,而重载可能有多个重载的方法。覆盖的方法有相同的方法名和形参表;而重载的方法只能有相同的方法名,不能有相同
6、的形参表。覆盖时根据调用它的对象来区分方法;而重载是根据形参表来决定调用的是哪个方法。5.1类的继承父类实例的父类实例的super引用引用如果需要在子类方法中调用父类被覆盖的实例方法,可以用super作为调用者来调用父类被覆盖的实例方法。publicclassOstrichextendsBird/子类中原有的内容publicvoidcallOverridedMethod()super.fly();/输出“我在飞”在子类中想调用父类被覆盖的方法fly可以通过super关键字实现5.1类的继承注意:super是Java提供的一个关键字,它是直接父类对象的默认引用。正如this不能出现在static
7、修饰的方法中一样,super也不能出现在static的方法中如果子类定义了和父类同名的属性,也会发生子类属性覆盖父类属性的情形。子类的方法直接访问该属性时,都会访问到覆盖属性,无法访问父类被覆盖的属性-通过super来访问父类被覆盖的属性例5.3子类属性覆盖父类属性的实例。如果我们在某个方法中访问名为a的属性,但没有显示指定调用者,系统查找a的顺序为:查找该方法中是否有名为a的局部变量查找当前类中是否包含名为a的属性查找a的直接父类中是否包含名为a的属性,依次上溯a的父类,直到java.lang.Object类,如果最终不能找到名为a的属性,则系统出现编译错误。5.1类的继承调用父类构造方法调
8、用父类构造方法子类不会继承父类的构造方法,但有的时候子类构造方法里需要调用父类构造方法的初始化代码。例写出下面程序的执行结果。classBaseprotecteddoublesize;publicBase()size=0;System.out.println(“Base类无参构造”);publicBase(doubles)size=s;System.out.println(“Base类有参构造”);5.1类的继承publicclassSubextendsBaseprivateStringcolor;publicSub()color=“blue”;System.out.println(“Sub类
9、无参构造”);publicSub(Stringc)color=c;System.out.println(“Sub类有参构造”);publicstaticvoidmain(Stringargs)Subs1=newSub();Subs2=newSub(“red”);当通过子类构造方法创建子类对象时,默认的先执行父类不含参数的构造方法,再执行子类类构造方法。5.1类的继承 要在子类中显式调用直接父类带参数的构造方法,可通过super()调用来实现。例如,publicSub(doubles,Stringc)super(s);/调用Base类中带一个参数的构造方法color=c;System.out.p
10、rintln(“Sub类有参构造”);注意:super调用和this调用很像,区别在于super调用的是其父类的构造方法,而this调用的是同一个类中重载的构造方法。因此,使用super调用父类构造也必须出现在子类构造执行体的第一行,所以this调用和super调用不会同时出现不会同时出现。5.1类的继承子类构造方法调用父类构造方法分如下几种情况:子类构造方法执行体的第一行代码使用super显示调用父类构造方法,系统将根据super调用里传入的实参列表调用父类对应的构造方法。子类构造方法执行体的第一行代码使用this显示调用本类中重载的构造方法,系统将根据this调用里传入的实参列表调用本类另
11、一个构造方法。执行本类中另一个构造方法时即会调用父类的构造方法。子类构造方法执行体中既没有super调用,也没有this调用,系统将会在执行子类构造方法之前,隐式调用父类无参数的构造方法。例5.5构造方法的调用顺序。上机实践1.请按如下要求定义两个A和B:类A中定义一个int类型变量z(将其赋值为16)、一个char类型变量x(将其赋值为65)和一个方法myPrint(),该方法的功能是在屏幕上输出z的值和x的值。类B是类A的子类,其中定义了一个double类型的变量y(将其赋值为16.0)和String类型的对象s(将其赋值为javaprogram!),还定义了两个方法myPrint()和p
12、rintAll(),方法myPrint()的功能是在屏幕上输出y和s的值,方法printAll()的功能是分别调用父类和子类的myPrint()方法。编写应用程序,创建B类的对象b,调用printAll()方法用来显示z、x、y、s的值。上机实践2.阅读下面程序,回答问题。publicclassApublicstaticvoidmain(Stringargs)Aa=newA();A()System.out.println(“A”);A(inti)this();System.out.println(“AA”);classBextendsAB()super();System.out.println
13、(“B”);B(inti)super(i);System.out.println(“BB”);上机实践(1)程序输出的结果是什么?(2)若将main()方法中的语句改为:Bb=newB(),程序输出的结果是什么?(3)若将main()方法中的语句改为:Bb=newB(1),程序输出的结果是什么?5.2多态性多态机制是面向对象技术的精华之一,它是建立在继承基础之上的。所谓多态(polymorphism),子类的对象可以子类的对象可以代替父类的对象使用代替父类的对象使用。思想基础思想基础在类的继承中,子类在父类的基础上进行扩充和改造,父类拥有的成员子类中都有,因而可以认为子类比父类的功能强,或者说
14、子类的对象应该比父类的对象功能强,因而子类的对象应可以替代父类的对象被使用。例5.6多态性使用举例1源文件:Person.java、Student.java5.2多态性publicclassTestpublicstaticvoidmain(Stringargs)Personp=newStudent();/System.out.println(p.getInfo();变量p声明为父类Person的类型,但实际指向的却是子类Student类型的对象5.2多态性一个对象只能属于一种确定的数据类型,该类型自对象创建直至销毁不能改变。一个引用类型变量可能引用(指向)多种不同类型的对象既可以引用其声明类型
15、的对象,也可以引用也可以引用其声明类型的子类的对象其声明类型的子类的对象。Objecto=newString(“hello”);Personp1=newString(“hello”);Students=newPerson();Object是所有类的父类Person类和String类之间不存在继承关系子类变量不能引用父类对象注意:由于父类对象未包含子类中添加的成员,因而功能较弱,也就无法替代子类对象使用。p.getSchool()5.2多态性例5.7多态性使用举例2publicclassTestpublicvoidshow(Person p)System.out.println(p.getInf
16、o();publicstaticvoidmain(Stringargs)Personp=newPerson();Students=newStudent();Testt=newTest();t.show(p);t.show(s);方法的形参声明为Person类型调用时实参既可以是Person类型,也可以是其子类Student类型注意:show方法既可以处理Person类型的数据,也可以处理Student类型的数据,乃至未来定义的任何Person子类类型的数据,这样就不必为相关的每一种类型单独声明一个处理方法,提高了代码的通用性代码的通用性。5.2多态性在多态情况下,一个引用类型的变量如果声明为父
17、类的类型,但实际引用的是子类对象,则该变量就不能访问子类变量就不能访问子类中添加的属性和方法中添加的属性和方法。可是如果此时调用的是父类中声明过,且在子类中又重写过的方法子类中又重写过的方法,情况又将如何?例5.8多态性示例3name、pricesetName()getName()setPrice()getPrice()show()Book类authorsetAuthor()getAuthor()show()Novel类5.2多态性publicclassTestNovelpublicvoidprocess(Bookb)b.show();publicstaticvoidmain(Stringar
18、gs)TestNovelt=newTestNovel();Bookb=newBook();b.setName(“EnglishLanguage”);b.setPrice(34);t.process(b);/方法体中的方法体中的b.show()输出结果?输出结果?B既可引用Book类对象,又可引用Novel对象,则这时调用的到底是Book类中的show方法还是Novel类中的show方法?5.2多态性若增加如下代码:Noveln=newNovel();n.setName(“theGreatWall”);n.setPrice(46.7);n.setAuthor(“Zhangsan”);t.proc
19、ess(n);/方法体中的方法体中的b.show()的输出结果?的输出结果?结论:系统依据运行时对象的真正类型来确定具体调用哪一个方法父类对象调用父类中的show方法,子类对象调用子类中重写过的show方法。5.2多态性 对象造型对象造型在多态的情况下,由于对象以其父类的身份出现,对子对子类中新添加成员的访问受到限制类中新添加成员的访问受到限制,有时我们可能需要恢复一个对象的本来面目造型(Casting),以发挥其全部潜力。例5.9多态性示例4。PublicclassTestpublicvoidcast(Personp)/System.out.println(p.getSchool();非法S
20、tudentst=(Student)p;/造型造型System.out.println(st.getSchool();/正确在main方法中:Testt=newTest();Students=newStudent();s.setSchool(“THU”);t.cast(s);5.2多态性所谓的造型造型其实就是引用类型数据值之间的强制类型转换。注意:从子类到父类的类型转换可以自动进行;在多态的情况下,从父类到子类转换必须通过造型(强制类型转换)实现;无继承关系的引用类型间的转换是非法非法的。Stringstr=“hello,world”;Personp=(Person)str;5.2多态性特别强
21、调:从父类到子类的造型也不是都能成功也不是都能成功只有当对象的真正类型本就是子类类型,只是在多态的情况下,被一个声明为父类类型的变量所引用,才可以进行造型处理,即再恢复该对象的本来面目,而一个对象如果其真正类型就是父类类型,是不能被造型为子类类型的。例如,Personp1=newPerson();Studentstu=(Student)p1;/编译没没错,但运行出,但运行出错5.2多态性 instanceof运算符运算符再看例5.9中Test类的cast方法:publicvoidcast(Personp)/System.out.println(p.getSchool();非法Studentst
22、=(Student)p;/造型造型System.out.println(st.getSchool();/正确调用方法时如果实参是子类Student的对象,则造型是正确的,若实参是父类Person的对象,则造型失败!则造型失败!if(pinstanceofStudent)Studentst=(Student)p;st.getSchool();5.2多态性运算符instanceof用于检测一个对象的真正类型。格式:instanceof功能:如果instanceof操作符左侧的变量当前时刻所引用对象的真正类型是其右侧给出的类型、或是其子类,则整个表达式结果为true,否则结果为false。例5.10
23、多态性示例5。在Test类中的cast方法可改写为:publicvoidcast(Personp)if(pinstanceofGraduate).elseif(pinstanceofStudent)PersonStudentGraduate上机实践1.定义类A和类B如下:classAfloatvar=1.1f;floatmethod()returnvar;classBextendsAfloatvar=2.2;floatmethod()returnvar;(1)类A和类B是什么关系?(2)类A和类B中都定义了变量var和方法method(),这种现象称为什么?(3)若定义Aa=newA(),则a
24、.var和a.method()的值是多少?(4)若定义Aa=newB(),则a.var和a.method()的值是多少?(5)若定义Aa=newB(),Bb=(B)a,则b.var和b.method()的值是多少?5.3静态初始化块Java使用构造方法构造方法来对单个对象进行初始化操作。与构造方法作用非常类似的是初始化块初始化块,它也可以对对象进行初始化操作。使用初始化块使用初始化块初始化块是Java类里可以出现的第四种成员。语法格式:class类名修饰符/初始化块的可执行代码初始化块一个类里可以有多个初始化块;相同类型的初始化块之间有顺序,前面定义的初始化块先执行,后面定义的初始化块后执行。
25、只能是static,静态初始化块可以定义局部变量、调用其他对象的方法、使用分支、循环语句等5.3静态初始化块例5.7初始化块的使用。分析:当创建Java对象时,系统总是先调用该类里定义的初始化块;如果一个类里定义了两个普通初始化块,则前面定义的初始化块先执行,后面定义的初始化块后执行。初始化块虽然也是Java类里的一种成员,但它没有名字,也就没有标识,因此无法通过类、对象来调用初始化块;初始化块只能在创建对象时自动执行而且在执行构造方法之前执行。5.3静态初始化块例5.8初始化块的使用。注意:初始块和声明实例属性时所指定的初始值都是该实例的初始化代码,它们的执行顺序与源程序中排列顺序相同。初始
26、化块和构造方法的不同:初始化块是一段固定的执行代码,它不能接受任何参数。因此初始化块对同一个类内的属性所进行的初始化处理完全相同。用法:如果多个构造方法里有相同的初始化代码,这些代码无需接受参数,那就可以把他们放在初始化块中定义。能更好的提高初始化块的复用,提高整个应用的可维护性。创建一个Java对象时,不仅会执行该类的初始化块和构造方法,系统会先执行其父类的初始化块和构造方法。5.3静态初始化块 静态初始化块静态初始化块如果定义初始化块时使用了static修饰符,则这个初始化块就变成了静态初始化块,也被称为类初始化块。静态初始化块是类相关的,系统将在类初始化阶段执类初始化阶段执行静态初始化块
27、行静态初始化块,而不是在创建对象时才执行,因此静态初始块总是比普通初始化块先执行比普通初始化块先执行。静态初始块属于类的静态成员,用于对类属性执行初始化处理,不能对实例属性进行初始化处理不能对实例属性进行初始化处理。系统在类初始化阶段执行静态初始化时,不仅会不仅会执行本类的静态初始化块,还会一直上溯到上溯到Object类类(如果它包含静态初始化块)。经过这个过程,才完成了对类的初始化过程。5.3静态初始化块例5.9写出程序的运行结果。第一次创建一个Leaf对象时,系统中不存在Leaf类,因此需要先加载类并初始化,初始化Leaf类时先执行顶层父类的静态初始化块,然后执行其直接父类的静态初始化块,
28、最后才执行Leaf本身的静态初始块。每次创建一个Leaf对象时,都需要执行最顶层父类的初始化块、构造方法,然后执行父类的初始化块、构造方法最后执行Leaf类的初始化块和构造方法。例5.10静态初始化块的使用。注意:静态初始块和声明静态属性时所指定的初始值都是该类的初始化代码,它们的执行顺序与源程序中排列顺序相同 5.5final修饰符final关键字可用于修饰类、变量和方法,用于表示它修饰的类、变量和方法不可改变。final变量变量final修饰变量时,表示该变量一旦获得了初始值之后就不可被改变不可被改变,final既可修饰成员变量(包括类变量和实例变量),也可以修饰局部变量、形参。final
29、修饰成员变量类变量:成员变量实例变量:当类初始化时,系统会为类变量分配内存,并赋默认值。当创建对象时,系统会为该对象的实例属性分配内存,并赋默认值。5.5final修饰符final修饰的类变量、实例变量能指定初始值的地方如下:类变量:静态初始化块或声明该属性时指定初始值。实例变量:非静态初始化块、声明该属性时或构造方法中指定初始值。例5.12编写程序,演示final修饰成员变量的用法。注意:实例属性不能在静态初始化块中指定初始值,因为静态初始化块是静态成员,不可访问实例属性非静态成员;类属性不能在普通初始化块中指定初始值,因为类属性在类初始化阶段已经被初始化了,普通初始化块不能对其重新赋值。5
30、.5final修饰符例5.13final成员的使用示例。publicclassTestfinalintage;System.out.println(age);/编译出错编译出错age=6;System.out.println(age);publicstaticvoidmain(Stringargs)newTest();注意:如果打算在构造方法、初始化块中对final成员变量进行初始化,则不要在初始化之前就访问成员变量的值。5.5final修饰符final修饰局部变量使用final修饰局部变量:可以在定义时指定默认值,则后面代码中不能再对该变量赋值。如果在定义时没有指定默认值,则可在后面代码中对
31、该final变量赋初始值,但只能一次,不能重复赋值。例5.14编写程序,演示final修饰局部变量、形参的情形。注意:test方法的形参用final修饰,则该形参由系统根据传入的参数来完成初始化。5.5final修饰符final修饰基本类型和引用类型变量的区别当用final修饰基本类型变量时,不能对基本类型变量重新赋值,即基本类型变量的值不能被改变区别引用类型变量保存的是一个引用,final只保证这个引用(地址)不会改变,即一直引用同一个对象,但这个对象可以发生改变。例5.15编写程序,演示final修饰基本类型和引用类型变量的区别。5.5final修饰符 final方法方法final修饰的方
32、法不可被重写不可被重写,如果出于某些原因,不希望子类重写父类的某个方法,则可以使用final修饰该方法。例5.16final方法举例。publicclassTestFinalMethodpublicfinalvoidtest()classSubextendsTestFinalMethodpublicvoidtest()出现编译错误final修饰的方法仅仅是不能被重写,并不是不不是不能能被重载。5.5final修饰符final类类final修饰的类不可有子类。例如,java.lang.Math类就是一个final类,它不可以有子类。例5.17编写程序,演示final修饰的类不可被继承。publi
33、cfinal classFinalClass/类中成员classSubextendsFinalClass将出现编译错误5.6抽象类 抽象方法抽象方法基类中定义的方法,有时候只有在派生类中才能写出方法体。例如,ShapeTwoDimensionalShapeThreeDimensionalShapeRectangleCircleEllipseCubeSphereCylinder需定义方法area()计算面积,能写出合适的方法体?5.6抽象类Java中,这种没有方法体的方法称为抽象方法抽象方法。抽象方法声明格式:修饰符abstract返回值类型方法名(形式参数表);抽象方法的特点抽象方法的返回值类
34、型前有关键字abstract;抽象方法没有方法体;抽象方法的定义是一行单独语句,以分号分号结束;在抽象方法声明中使用static修饰符是错误的。例如,publicabstractdoublearea();5.6抽象类 抽象类抽象类类中如果定义了抽象方法,这个类必须定义为抽象类。publicabstractclass类名/类体(属性、非抽象方法、抽象方法、构造方法)/类体(初始化块、内部类、枚举类)抽象类不能创建自己的对象,使用new创建抽象类对象将产生错误。子类继承抽象类时,应该覆盖抽象类中的所有抽象方法,否则子类也必须定义为抽象类。5.6抽象类注意含有抽象方法抽象方法的类(包括直接定义了一个
35、抽象方法;继承了一个抽象父类,但没有完全实现父类包含的抽象方法)只能被定义成抽象类抽象类。但抽象类中却并并一定一定包含抽象方法。抽象方法和空方法体的方法不是同一个概念publicabstractvoidtest();publicvoidtest()是一个抽象方法,它根本没有方法体,即方法定义后面没有一对花括号一个普通方法,定义了方法体,只是方法体为空,因此这个方法不可以使用abstract来修饰5.6抽象类例5.18抽象类示例。publicabstractclassShapepublicabstractdoublecalcArea();publicShape()publicShape(Stri
36、ngname)System.out.println(name+ShapeCreated);publicStringtoString()System.out.println(“thisisShape!”);抽象方法构造方法不用于创建Shape对象,而是用于被子类调用抽象类,不能实例化的5.6抽象类publicclassCircleextendsShapepublicfloatr;privatefinalfloatPI=3.14;publicCircle(Stringname,floatr)super(name);this.r=r;publicfloatcalcArea()returnPI*r*r
37、;子类Circle,必须重写Shape类中的抽象方法,否则Circle就是一个抽象类5.6抽象类注意final和abstract永远不能同时使用。abstract不能用于修饰属性,不能用于修饰局部变量,即没有抽象变量、没有抽象属性等说法;abstract也不能用于修饰构造方法,没有抽象构造方法。抽象类里定义的构造方法只能是普通构造方法。static和abstract不能同时修饰某个方法,即没有所谓的类抽象方法。abstract关键字修饰的方法必须被其子类重写才有意义,否则这个方法将永远不会有方法体,因此abstract方法不能定义为private访问权限。5.6抽象类抽象类的作用抽象类的作用代
38、码重用代码重用子类可以重用抽象父类中的属性和非抽象方法;规划规划抽象类中通过定义抽象方法规划了其所有子子类必须要实现的功能类必须要实现的功能,或者说指定了其子类对象与外界的交互界面,因为抽象方法的方法头部分已经规定了该方法将来被子类对象调用的格式。模板模式的设计5.6抽象类模板模式:抽象类作为多个子类的通用模板,子类在抽象类的基础上扩展、改造,但子类总体上会保留抽象类的行为方式。抽象类不能实例化,但抽象类可作为变量的类型变量的类型和方法方法形参类型形参类型,可将抽象类子类的对象抽象类子类的对象赋给该变量或做方法的实参。例如,Shapes=newRectangle();publicstaticS
39、tringShowShapinfo(Shape item)if(iteminstanceofRectangle)Rectangler=(Rectangle)item;/其他代码5.7接口接口是另一种定义数据类型的方式。它和类非常相似的。相同之处:都有成员变量和成员方法 也可以形成继承关系不同之处:接口中的属性都是常量(final)接口中的方法是抽象方法(没有方法体)引入接口的原因引入接口的原因:Java只支持单重继承,每个类只能有一个超类。但实际应用中有时候需要多重继承多重继承使用接口使用接口,一个类可以实现多个接口。接口的概念接口的概念类比:计算机的USB口5.7接口接口的定义接口的定义pu
40、blicinterface接口名extends父接口1,父接口2,publicstaticfinal数据类型属性名=常量值;publicabstract返回值类型方法名(形参表);表示可以被不同包中的类或接口使用,缺省时具有包内可访问性interface关键字表示接口任意有效标识符接口支持多继承,多个父接口之间用逗号分隔接口的属性必须用publicstaticfinal修饰,是系统默认的,可部分省略或全部省略,但一般都写出final。intMAX_SIZE=50;等价于publicstaticfinalintMAX_SIZE=50;接口的方法默认为publicabstract,一般不写修饰符,
41、可省略接口中的方法都是抽象方法接口中的方法都是抽象方法。5.7接口例5.19接口的定义。publicinterfaceFigurefinaldoublepi=3.14;abstractvoidarea();实现接口实现接口 接口定义后不能直接不能直接创建对象,必须由类实现接口后创建类的对象。每个类只能继承一个基类,但可以实现多个接口。类定义形式如下:5.7接口publicclass类名extends基类implements接口1,/类体注意:类实现接口,就继承了接口中的所有成员变量和成员方法。由于接口中的方法都是抽象的,因此实现接口的类必须重写这些方法。publicclassCircleimp
42、lementsFiguredoubleradius;publicCircle(doubler)radius=r;publicvoidarea()System.out.println(圆的面积=+pi*radius*radius);可实现多个接口,多个接口之间用逗号分隔5.7接口注意:注意:实现接口中的抽象方法时,除去掉关键字abstract外,方法头必须和接口定义中的方法头完全相同,并且public修饰符不能省略修饰符不能省略。如果类实现了多个接口,必须重写这些接口中的所有方法。接口不是类,不能使用new实例化接口,但可以声明接口变量。接口变量可以指向一个实现了该接口的类的对象,例如,Shap
43、es=newShape();/错错Shapes=newCircle();/对对5.7接口可以使用instanceof来判断对象是否实现了某个接口。虽然可以使用接口变量来引用实现接口类的对象,但这种引用只能引用接口的成员,否则会发生编译错误。例如,classRectangleimplementsShapeShapes;s=newCircle();s.area();s=newRectangle();s.area();例5.21接口的定义与实现。调用的是同一方法吗?多态强调:一个接口定义一个协定,实现接口的类必须遵守其协定。接口最适合为不相关的类提供通用功能,利用接口提供的方法,程序可以多态地处理这
44、些完全不同的类的对象。5.7接口 接口的继承接口的继承接口具有多重继承的特点,即一个接口可以有多个父接口。新的子接口继承所有父接口的全部方法和常量。接口继承的格式为:publicinterface子接口extends父接口1,父接口2,/静态属性;/抽象方法;例5.20接口的继承。5.7接口 接口和抽象类接口和抽象类接口和抽象类很像,它们都具有如下特征:接口和抽象类都不能被实例化,它们都位于继承树的顶端,用于被其他类实现和继承。接口和抽象类都可以包含抽象方法,实现接口或继承抽象类的普通子类都必须实现这些抽象方法。区别设计目的不同接口体现的是一种规范,类似于整个系统的“总纲”,它制定了系统各模块
45、应该遵循的标准。因此一个系统中的接口不应该经常改变抽象类作为多个子类的共同父类,体现的是模板式设计。抽象类可以被当成系统实现过程中的中间产品,这个中间产品已经实现了部分功能,但这个产品还不能当成最终产品,必须更进一步的完善,这种完善可能有几种不同方式。5.7接口用法不同(1)接口里只能包含抽象方法(2)接口里不能定义静态方法(3)接口里只能定义静态常量属性(4)接口不包含构造方法(5)接口里不能包含初始化块(6)一个类可以实现多个接口(1)抽象类可以包含普通方法。(2)抽象类可以定义静态方法(3)抽象类既包含普通属性,也可以包含静态常量属性(4)抽象类里构造方法不用于创建对象,是让子类调用(5
46、)抽象类可以包含初始化块(6)一个只能继承一个父类上机实践1.定义一个接口,接口中有三个抽象方法:longfactorial(intm);/求参数的阶乘longmyPower(intm,intn);/求参数m的n次方booleanfindFactorSum(intm,intn);/判断参数中较小数是否是较大数的因子定义类实现该接口。编写应用程序,调用接口中的三个方法,并将调用这些方法得到的结果输出。上机实践2.编写一个Animal类,包含:属性:privateStringtype;/动物的类型构造方法:/用于初始化私有属性type方法:publicStringtoString()/返回动物类型
47、信息publicvoidsound()/输出动物的叫声信息3.编写一个Flyable接口,包含方法:doubleflySpeed();/用于返回最大的飞行速度4.编写Glede(老鹰)类和Pigeon(鸽子)类,分别继承题2中的Animal类并实现题3中的Flyable接口。编写测试类,打印输出老鹰和鸽子的叫声信息和最大飞行速度。5.8内部类一个Java程序就是一个类的集合。程序中的类有两种排列结构。类1Java程序类2类n外部类Java程序内部类类k在一个类中定义其它类5.8内部类例如:classEnclosingClassclassANestedClass内部类在外部类中有特权特权:内部类
48、可以毫无限制地访问外部类的所有成员所有成员。编译之后,内部类也可产生单独的.class文件,文件名为:外部类名$内部类名.class5.8内部类例5.22内部类使用示例。publicclassOuterClassprivateintx=10;classInnerClassinty=20;publicstaticvoidmain(Stringargs)OuterClassoc=newOuterClass();OuterClass.InnerClassic=oc.newInnerClass();System.out.println(Outer:x=+oc.x);System.out.println
49、(InnerClass:y=+ic.y);内部类是外部类的一个成员,内部类对象不能单独存在,它必许依赖一个外部类对象5.8内部类使用内部类在编写事件处理驱动的程序编写事件处理驱动的程序时用起来很方便。只有内部类才能够是私有的私有的安全机制,只有其外部类的方法才能够创建内部类对象。5.9匿名类如果只需要为内部类建立一个对象,甚至不必为该类指定一个名字,这种类被称为匿名内部类。如果满足下面的一些条件,使用匿名内部类是比较合适的:只用到类的一个实例类在定义后马上用到类非常小(推荐在4行代码以下)给类命名并不会导致你的代码更容易被理解5.9匿名类newActionListener()publicvoi
50、dactionPerformed(ActionEvente);class类名implementsActionListenerpublicvoidactionPerformed(ActionEvente)new类名();由于匿名内部类没有名称,因此创建匿名内部类对象时,new运算符后是超类或接口的名称,其后的内部为匿名类的定义(匿名类对象的创建和匿名类的声明是在一起的)。5.9匿名类匿名类不能是抽象类,因为系统在创建匿名类的时候,会立即创建匿名类的对象。因此不允许将匿名类定义成抽象类。匿名类不能有构造方法,因为匿名类没有类名,无法定义构造方法,但匿名类可以定义实例初始化块,通过实例初始化块来完成