《Java面向对象编程进阶.ppt》由会员分享,可在线阅读,更多相关《Java面向对象编程进阶.ppt(42页珍藏版)》请在三一办公上搜索。
1、第5章 Java面向对象编程进阶,5.1 内部类和匿名类(略)5.2 抽象类 5.3 继承 5.4 包 5.5 接口,abstract class Shape/说明一般二维图形抽象类 abstract double area();/计算图形面积的方法 abstract void draw();/绘制图形的方法,有时,由于对象高级抽象的需要,希望类只需要说明方法首部,而不需要或不可能说明其方法体,其方法体只能由其子类来完成,这样的类需要使用abstract关键字修饰,这种类被称为抽象类。抽象类不能创建任何对象,抽象类只是用来由其子类继承。继承抽象类的子类比它的父类更加具体化、特殊化。例5-1 抽
2、象类Shape,5.2 抽象类,class Rectangle extends Shape/矩型类Rectangle继承了Shape类 int width;/矩形的宽 int length;/矩形的长 punlic double area()return width*length/矩形类实现了Shape类的抽象方法area()public void draw()/这里要实现Shape类的抽象方法draw(),5.3 继承,继承概述 继承语法格式 子类对父类成员重载 null,this,super 多态性 final类(最终类),在Java编程语言中,通过继承可利用已有的类,并扩展它的属性和方法
3、。这个已有的类可以是语言本身提供的、其他程序员编写的或程序员原来编写的。如果在声明类A时,指明类A继承了类B(类B是一个已定义了的类),则类A通常就拥有了类B的成员变量和方法。此时,类B称为类A的父类(superclass),父类也称为超类或基类;类A称为类B的子类(subclass),子类也称为派生类。Object类是Java中所有类的父类,也就是说Java中的类直接或间接有Object类派生而来。Java中实行单继承,即一个类只能有一个父类。,5.3.1 继承概述,一个类只可继承一个父类,但一个类可以有被多个子类继承。因而类之间的关系就形成了所谓的树形层次结构:,类A,类C1n,类C11,
4、类Bm,类B2,类B1,类Cm1,类Cmn,在Java中,类是Java所有类的父类。,类继承语法形式如下:修饰符 class SubClassName extends SupperClassName extends是继承关键词。SubClassName是新的子类名,SupperClassName是继承的父类名。父类名是必需的,而且只能有一个,因为Java中实行单继承。父类名所指定的类必须是在当前编译单元中可以访问的类,否则会产生编译错误。,继承语法格式,子类的特性:子类拥有其父类的所有属性和方法。但父类中说明为private的属性和方法,子类不可直接访问。子类可以对父类的方法覆盖或重载。,例.
5、5-2子类与父类,class A private int a;protected int b;public int c;public void setA(int aa)a=aa;public int getA()return a;class B extends A int d;public static void main(String args)B b1=new B();b1.setA(10);b1.b=20;b1.c=30;b1.d=b1.getA()+b1.b+b1.c;System.out.print(b1.d);,子类可以对父类的方法覆盖或重载。方法覆盖:子类的方法首部与父类的方法首
6、部相同,但是子类重新实现了该方法。方法重载:Java中方法可重载,就是方法名相同但形参列表不同之方法。子类的方法对父类的方法也可重载。,5.3.3 子类对父类成员重载,如果子类声明了一个与父类的成员变量同名的成员变量,则称父类的该成员变量被隐藏(Hiding),如果子类声明了一个与父类的成员方法同名的成员方法,则称父类的该成员方法被重写(Overriding)。关键字this和super分别用来指明子类和父类中同名的成员变量和方法。当父类的成员变量、子类的成员变量和类的对象方法使用的局部变量三者同名,或其中两个同名时,可以使用关键字this和super来指定所要使用的变量。继承是面向对象编程的
7、主要优点之一,它对如何设计Java类有着直接的影响。继承有如下几点好处:,(1)它可以利用已有的类来创建自己的类,只需要指出自己的类和已有的其它的类有什么不同即可,而且还可以动态访问其它有关的类中的信息。(2)通过继承,可以利用Java类库所提供的丰富而有用的类,这些类都已经被很好地实现。(3)当设计很大的程序时,继承可以使程序组织得更加层次清晰,有利于程序设计和减少错误的发生。,例5-3 子类与父类的继承关系,public class Point/定义Point类 int x;int y;,public Point()/构造方法,构造原点(0,0)x=0;y=0;public Point(i
8、nt X,int Y)/构造方法,按给定的X、Y 值 x=X;y=Y;/构成一个点(X,Y)public double distance()/定义方法,求点到坐标原点的距离 return Math.sqrt(x*x+y*y);/调用Math类的方法sqrt()public static void draw()/类方法draw(),画点 System.out.println(Point:a point.);,class ColorPoint extends Point int color;public static void draw()/复盖了父类的draw()方法 System.out.pr
9、intln(“ColorPoint:a color point.”);class MapPoint extends ColorPoint/定义类,继承ColorPoint类/类Object、Point均是MapPoint的父类,但都不是直接父类String name;/地图上的点有自己的名字,如城市名 public static void draw()/复盖了父类的draw()方法 System.out.println(MapPoint:a map color point.);,public class SuperSub public static void main(String args)
10、Point.draw();ColorPoint.draw();MapPoint.draw();,此程序运行后将输出如下结果:Point:a point.ColorPoint:a color point.MapPoint:a map color point.,null、this、super,Java语言规范中,每个类均有这样3个对象:null、this、super null“空”变量,表示这个对象不存在相应的实例 例如:Rectangle rect=null;当一个对象不再有用时,应当清除它以释放所占用的内存空间,这只要赋予它null即可。即如:rect=null;,this 代表对象本身 在类
11、的方法中,如果要引用的变量名或方法名的成员变量名或成员方法名相同,则可通过使用this 来代表对象本身,即引用对象自身。super 代表父类 当子类中有与父类同名的变量或方法时,可加上super限定词来指明是对父类的变量或方法的引用。下面是this和super是使用的例子。,class Rectangle int width,length;Rectangle(int width,int length)/构造方法 this.width=width;/this代表所创建的对象 this.length=length;public void drawRect()System.out.println(t
12、his is Rectangle!);,例5-4 用this表示引用自身,上面这个例子中,用this表示引用对象本身。,在构造方法中,可以使用super来引用父类的构造方法。例5-5 用super引用父类的构造方法,class fillRectangle extends Rectanglepublic fillRectangle(int w,int num)/构造方法 super(w,num);/调用父类的构造方法 private String makeString(char ch,int num)StringBuffer str=new StringBuffer();for(int i=nu
13、m;i0;i-)str.append(ch);return str.toString();,在这个类的构造方法中并没有写新的程序,而是调用了父类的构造函数,用于初始化实例变量。,public void drawRect()for(int i=length;i0;i-)/用字符“#”绘制(填满)一个矩形 System.out.pringln(makeString(#,width);,例.5-6 用 super 指明引用父类的变量,class A String str=aaaaa;class B extends A String str=bbbbb;void f()System.out.print
14、ln(父类变量str:+super.str);System.out.println(子类变量str:+str);public static void main(String args)B b1=new B();b1.f();,例.5-7 对象变量、静态变量的继承。,class A static int a;int b;class B extends Apublic static void main(String args)A.a=10;B.a=20;System.out.println(A.a=+A.a+,B.a=+B.a);A a1=new A();B b1=new B(),b2=new B
15、();a1.b=3;b1.b=4;b2.b=5;System.out.println(a1.b);System.out.println(b1.b);System.out.println(b2.b);,final修饰符可以定义一个不能被继承的类,即不能再有子类。类就是final类的一个例子,它是最终的类。final修饰符通常是出于安全的目的而使用的,因为不能继承final类,人们就不能重载或覆盖它的任何方法。如果允许一个类被继承,其被重载或覆盖的方法可能会被改写。保证某个特定的方法在类层次关系上的某层以后只有一个定义,这对于那些安全性非常关键的类是非常必要的。无论是用于修饰变量、方法还是类,fi
16、nal关键字的目的都是一样的:增强代码的安全性。例4.8 final类说明final class EndClass extends SupperClass,final类(最终类),包说明 包的层次结构 包的使用,5.4 包,包是为了解决设计较大规模的程序而引入的概念。一个大的系统,往往包含多种对象,需要多个类来描述。这些类以逻辑方式组合在一起,形成了所谓的包。使用包可提供控制访问的范围。类、方法缺省访问权限时,就只可在它所属的包中被访问,说明为public的才可在其他包中被访问。一个Java程序可以由多个包组成。一个包可由一个或多个源程序文件(.java文件)构成,有多个源程序文件时要分别建立
17、。注意:每个源程序文件中最多只能有一个说明为public的类。,包说明语句总是源程序文件中的第一个语句(可省略),其格式如下:package 包名;例.5-8 包说明上面的程序定义了一个包含3个类的包。,包说明,package SamplePackage;public class Class1 class Class2 class Class3,包中多个类之间不可嵌套定义,但前后位置无关。,在Java中,包采用如下的层次结构:子包 类文件和接口文件(一个类或一个接口编译后都产生一个相应的字节码文件)由于包的层次结构类似文件夹的层次结构,所以,为了实现上的简单,Java对包的存储作了一定的规定。
18、系统中所有的Java包、类的源文件、字节码文件都必须存放在单一文件夹下或它的子文件夹中。在实际的Java开发环境中,通常提供了一个名为CLASSPATH的环境变量,这个环境变量中包含了一系列的路径名,它们就是存储Java类、接口和包的路径。系统将按照环境变量CLASSPATH中路径出现的先后顺序逐个搜索,来寻找某个类、接口或包。以下是一个Windows 环境变量的例子:CLASSPATH=C:JDKlib;C:JDKsrc;,包的层次结构,1.用户自己定义的包的使用例5-9 包的使用,包的使用,/文件:packoneClassBeUsed.javapackage packone;/定义包pac
19、konepublic class ClassBeUsed private int counts;ClassBeUsed()/无参构造方法 setcounts(0);ClassBeUsed(int i)/有参构造方法 setcounts(i);protected void setcounts(int i)counts=i;public int getcounts()return counts;,上面的程序中创建了两个包packone和packtwo。在packone 包中定义了一个 public类 classBeUsed,在packtwo包中定义了一个 public类 UsingClass。,/
20、文件:packtwoUsingClass.javapackage packtwo;/定义包packtwopublic class UsingClass public static void main(Stringargs)ClassBeUsed cb=new ClassBeUsed(2);/创建包 packone的ClassBeUsed类的实例cb System.out.println(cb.getcounts();,packtwo的UsingClass类的main方法中的语句:ClassBeUsed cb=new ClassBeUsed(2);是要创建包packone的ClassBeUsed
21、类的实例cb。,编译里例5-9中的程序,则会产生如下的错误:Undefined name ClassBeUsed Cannot find definition for class ClassBeUsed原因何在?仔细地观察程序:,package packone;public class ClassBeUsed private int counts;ClassBeUsed()/无参构造方法 setcounts(0);ClassBeUsed(int i)/有参构造方法 package packtwo;public class UsingClass public static void main(S
22、tringargs)ClassBeUsed cb=new ClassBeUsed(2);System.out.println(cb.getcounts();,/文件:packoneClassBeUsed.javapackage packone;public class ClassBeUsed private int counts;public ClassBeUsed()/构造方法声明为public setcounts(0);public ClassBeUsed(int i)/构造方法声明为public setcounts(i);,现在对例5-9程序做一些修改,改正后的程序如下:,/文件:pac
23、ktwoUsingClass.javapackage packtwo;import packone.ClassBeUsed;/引入包packtwo的类ClassBeUsedpublic class UsingClass public static void main(String args)ClassBeUsed cb=new ClassBeUsed(2);System.out.println(cb.getcounts();,/文件:packtwoUsingClass.Javapackage packtwo;public class UsingClass public static void
24、main(String args)packone.ClassBeUsed cb=new packone.ClassBeUsed(2);System.out.println(cb.getcounts();,也可如下修改:,2.系统包的使用 Java系统中建立了很多非常有用的包,供用户使用。这些包以“java.”开头,作为java 的一个标准部分发布的。其使用方法与用户自定义的包一样,只需要在程序开始处(包定义语句后)加上import 语句引入所需包中的类即可。其格式如下:import 包名.类名;或:import 包名.*;学习Java,必须学习Java 常用包中的类。从第六章开始,将叫详细地介
25、绍Java常用包的使用。,引入某包的一个类,引入某包的所有类,一个Java程序可以由多个包组成。如果想使一个类能被其它包引用,那么该类必须是由public修饰的类(公共类),其构造方法也必须声明为public。要创建一个非本包的公共类的实例时,可以使用两种方法:(1)在类名前带上包名加以限定(2)在程序头部(包定义语句后)使用import 语句引入所需包中的类。,包小结,5.5 接口,接口的概念 接口的说明 接口的使用,类体的结构:一个类的类体由一些成员变量和一些成员方法组成。如果一个类的类体中仅含有final修饰的成员变量(即常量)和一些抽象的成员方法(方法框架,即方法体只是个分号),则这样
26、的类就改叫做接口(interface),而不再叫做类,即接口就是一些常量和抽象方法的定义的集合,它是一个设计框架。接口中的方法只是一个定义框架而没有具体的实现代码,所以接口是不能象类一样建立实例,而只能再用类来实现接口中的方法,然后我们再引用这样的类。,5.5.1 接口的概念,接口是面向对象的一个重要思想,利用接口的“设计与实现分离”的特性,使利用接口的程序不受不同接口实现的影响,不受接口实现改变的影响。软件设计者在设计程序时,也许只想设计一个框架,如只提供一个类的抽象的接口,而不希望去具体实现它。使用接口就可以很完美地解决这个问题。,接口可以继承 和类不同,一个接口可以继承多个其它的接口,也
27、就是说,接口是支持多继承的。接口中的方法要用类来实现 一个类说明实现一个接口,就是承诺它将实现接口中声明的所有方法。一个类可以实现多个接口 一个接口也可以被多个类实现 接口可以多继承,即一个接口可以有多个父接口,但和类的继承不同,子接口只是从父接口那里继承了方法的说明,而不会有方法的实现和实例变量的说明。这样,就降低了完全多继承所带来的复杂性。,小结:接口和类之间的区别(1)类只能单继承,而接口可以多继承。(2)类中的方法可以是具体的,也可以抽象的。接口中的方法都是抽象的。(3)接口中的方法要用类来实现,一个类可以实现一个接口,也可以实现多个接口。(4)对于继承性,子类可以直接继承父类的方法,
28、也可以覆盖父类的方法。而子接口仅从父接口那里继承了方法的说明,并没有方法的实现。因此,任需要用类来实现子接口中的所有方法。,5.5.2 接口的说明,接口类型的说明类似于类的说明,它由两部分组成:接口说明和接口体。接口首说明 接口体 像类一样,编译好的接口保存在Class文件中。,接口首说明的形式如下:修饰符 interface 接口名 extends 接口序列 interface是关键字,表示定义接口。修饰符是可选的。当没有修饰符的时候,表示此接口的访问只限于同包的类。如果使用修饰符,则只能用public修饰符,表示此接口是公有的,在任何地方都有可以引用它,这一点和类是相同的。接口说明中的ex
29、tedns关键词和类说明中的extends一样,用来定义直接的父接口,当extends后面有多个父接口时,它们之间用逗号隔开。一个最简单的接口说明:public interface Cookable extends Foodable,Printable 接口体,接口首说明,接口体说明接口的成员常量和抽象方法。/接口体开始 常量说明 抽象方法说明/接口体结束例.5-10 接口说明,接口体,interface Countablefinal int MALMUM=50;/定义一个常量 void incrementCount();/定义一个无参的抽象方法 void decrementCount();/
30、定义第二个抽象方法 int currentCount();/定义第三个抽象方法 int setcount(int newcount);/定义第四个抽象方法,有参数,接口体说明注意点:(1)接口中的成员变量(常量)说明 声明形式:修饰符 类型名 变量名;接口中的成员变量的修饰符都只能用public、static、final,而且也都隐含着修饰符,所以修饰符是不必写的。就是说,接口中的成员变量都是公用的静态最终变量,即公用的静态常量。例如:在接口中,下面这行代码:int STEP=5;等同于:public static final int STEP=5;(2)接口中的方法 接口中说明的方法都是抽象
31、方法,其声明的形式为:修饰符 方法返回值类型 方法名(参数列表);,由于接口中的方法都是抽象的方法,所以方法体仅仅是一个分号“;”。方法的修饰符只能是public、abstract。接口中所有的方法都隐含着修饰符public、abstract,所以,加不加修饰符是一样的。(只是为了和以前版本的Java兼容,所以才保留这两个修饰符在接口中对方法的使用)例.接口中的方法说明 int increment(int x);,接口自己不能提供方法的实现,接口中的方法必须由类实现。如果一个类将实现某些接口,则首先要在类的说明中指明那些接口在此类中被实现。Java语言用关键字implements声明类中将要实
32、现的接口。在implements子句中可以包含多个接口,各个接口类型之间用逗号隔开,实现接口的类的类首形式如下:类修饰符 class类名 extends子句 implements 子句 其中,implements子句的形式如下:implements 接口名列表,5.5.3 接口的使用,public interface MyInterface/接口 void display();public class MySample implements MyInterface/实现接口的类 public void display()/实现MyInterface接口中的方法 System.out.print
33、ln(Display!);public static void main(String args)MySample My1=new MySample();My1.display();,例.5-11 接口的使用,接口是面向对象的一个重要思想,利用接口使设计与实现分离,使利用接口的用户程序不受不同接口实现的影响,不受接口实现改变的影响。接口在Java中还起着另一个非常重要的作用,弥补Java只支持单继承的不足,它用来完成多继承的一些功能。Java接口反映了对象分析中较高层次的抽象,为描述相互似乎没有关系的对象的共性提供的一种有效的手段。包是为了解决一个大的问题、设计较大规模的程序而引入的概念。使用包可以提供一定的访问控制。类、方法缺省访问权限就是可以在它所属的包中被访问。说明为public的类、方法才可以在其他它包中被访问。如果类和方法被说明为protected,则其他它包中只有它的子类才可以访问它们。,章小结,