《java程序设计第六章 面向对象编程的深入讨论.pdf》由会员分享,可在线阅读,更多相关《java程序设计第六章 面向对象编程的深入讨论.pdf(16页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。
1、2010/11/22010/11/21 1JAVA语言程序设计语言程序设计Java程序设计程序设计主讲教师:张思民主讲教师:张思民面向对象编程的深入讨论第六章2目标 构造函数的执行机制 屏蔽、覆盖和重载 对象间的类型转换 对象乊间的比较2010/11/22010/11/22 236.1 6.1 构造函数的执行机制 构造函数的作用:对创建的对象进行初始化 类的继承机制:子类可以使用父类的功能(即代码),那么子类对象的初始化要使用到父类的构造函数。4class class SuperClass SuperClass SuperClass()SuperClass()SystemSystem.out.
2、println(SuperClass constructor);.out.println(SuperClass constructor);publicpublic classclass SubClassSubClass extendsextends SuperClassSuperClass SubClass()SubClass()SystemSystem.outout.println(println(SubClassSubClass constructorconstructor);publicpublic staticstatic voidvoid main(main(StringString
3、 args)args)SubClassSubClass subsub=newnew SubClass()SubClass();例子例子6 61 1类在继承关系上的初始化的顺序类在继承关系上的初始化的顺序2010/11/22010/11/23 35例子例子6 61 1在子类中只实例化了一个子类对象。在子类中只实例化了一个子类对象。从输出结果上看:从输出结果上看:程序并不是一开始就运行自己的构造方法,程序并不是一开始就运行自己的构造方法,而是先运行其父类的默认构造方法。而是先运行其父类的默认构造方法。注意:程序自动调用其父类的默认构造方法。注意:程序自动调用其父类的默认构造方法。子类对象初始化子类
4、对象初始化父类父类构造函数构造函数6classclass SuperClassSuperClassSuperClass(StringSuperClass(String str)str)SystemSystem.outout.println(Superprintln(Super withwith a a stringstring.);publicpublic classclass SubClassSubClass extendsextends SuperClassSuperClassSubClass(StringSubClass(String str)str)SystemSystem.outou
5、t.println(Subprintln(Sub withwith a a stringstring.);publicpublic staticstatic voidvoid main(Stringmain(String args)args)SubClassSubClass subsub=newnew SubClass(sub)SubClass(sub);SubClass未找到其父类的默认构造方法SuperClass()SuperClass(),编译通丌过SuperClass();SuperClass();方法方法1 1:在父类中增加在父类中增加一个默认构造方法。一个默认构造方法。SuperC
6、lass();SuperClass();/SuperClass();/SuperClass();super(str);super(str);方法方法2 2:在子类的构在子类的构造方法中第一句增造方法中第一句增加加“super(str)super(str)”例6-2:2010/11/22010/11/24 47publicpublic classclass TestTest publicpublic staticstatic voidvoid main(Stringmain(String args)args)SystemSystem.outout.println(Testprintln(Test
7、 main()main();CarCar carcar=newnew Car(car)Car(car);输出结果为:输出结果为:Test main()Test main()wheelwheel-1 1 wheelwheel-2 2 wheelwheel-3 3 carcar例6-3:对象的初始化顺序问题在main()方法中初始化car类的对象时,先初始化car类的成员变量,(成员变量是wh对象则调用该对象相应的构造方法)。而后再初始化car类的对象,即调用car类的构造方法class Wheel class Wheel Wheel(String str)Wheel(String str)Sys
8、tem.out.println(str);System.out.println(str);classclass carcar WheelWheel wheel_wheel_1 1=newnew WheelWheel(wheel(wheel-1 1);WheelWheel wheel_wheel_2 2=newnew WheelWheel(wheel(wheel-2 2);WheelWheel wheel_wheel_3 3=newnew WheelWheel(wheel(wheel-3 3);Car(StringCar(String str)str)SystemSystem.outout.pr
9、intln(str)println(str);8例6-3:对象的初始化顺序 在创建对象时,对象所在类的所有数据成员会首先进行初始化 如果其中的成员变量有对象,那么它们也会按照顺序执行初始化工作。在所有类成员初始化完成后,才调用对象所在类的构造方法创建对象。构造方法作用就是初始化。在test类中创建car对象时,先初始化“car”类的成员变量成员变量wheel_1wheel_1,wheel_1wheel_1,wheel_1wheel_1等按顺序初始化最后调用carcar类的构造函数2010/11/22010/11/25 59publicpublic classclass TestTest pub
10、licpublic staticstatic voidvoid main(main(StringString args)args)SystemSystem.outout.println(Testprintln(Test main()main();CarCar car_car_1 1=newnew car(carcar(car-1 1);SystemSystem.outout.println(println(-);CarCar car_car_2 2=newnew car(carcar(car-2 2);如一个类有静态对象,那么它会在非静态对象前初始化,但只初始化一次classclass car
11、car WheelWheel wheel_wheel_1 1=newnew Wheel(Wheel(“wheelwheel-1 1”);WheelWheel wheel_wheel_2 2=newnew Wheel(wheelWheel(wheel-2 2);staticstatic WheelWheel wheel_wheel_3 3=newnew Wheel(wheelWheel(wheel-3 3);Car(StringCar(String str)str)SystemSystem.outout.println(str)println(str);classclass Wheel Whee
12、l Wheel(String str)Wheel(String str)SystemSystem.out.println(str);.out.println(str);例64:输出结果:输出结果:Test main()Test main()wheelwheel-3 3 wheelwheel-1 1 wheelwheel-2 2 carcar-1 1-wheelwheel-1 1 wheelwheel-2 2 carcar-2 2 10classclass carcar WheelWheel wheel_wheel_1 1=newnew Wheel(wheelWheel(wheel-1 1);W
13、heelWheel wheel_wheel_2 2=newnew Wheel(wheelWheel(wheel-2 2);staticstatic WheelWheel wheel_wheel_3 3=newnew Wheel(wheelWheel(wheel-3 3);Car(StringCar(String str)str)SystemSystem.outout.println(str)println(str);例6-5public class Test static Car car_3=new Car(car-3);publicpublic staticstatic voidvoid m
14、ain(Stringmain(String args)args)System.out.println(Test main();Car car_1=new Car(car-1);System.out.println(-);Car car_2=new Car(car-2);输出输出:wheelwheel-3 3wheelwheel-1 1wheelwheel-2 2carcar-3 3TestTest main()main()wheelwheel-1 1wheelwheel-2 2carcar-1 1-wheelwheel-1 1wheelwheel-2 2carcar-2 2程序中主类的静态变量
15、会在main()方法执行前初始化。classclass Wheel Wheel Wheel(String str)Wheel(String str)SystemSystem.out.println(str);.out.println(str);2010/11/22010/11/26 611classclass carcar staticstatic intint i i=0 0;WheelWheel wheel_wheel_1 1=newnew Wheel(wheelWheel(wheel-1 1);staticstatic WheelWheel wheel_wheel_2 2=newnew
16、Wheel(wheelWheel(wheel-2 2);staticstatic WheelWheel wheel_wheel_3 3=newnew Wheel(wheelWheel(wheel-3 3);car(Stringcar(String str)str)SystemSystem.outout.println(str)println(str);publicpublic classclass TestTestpublicpublic staticstatic voidvoid main(Stringmain(String args)args)SystemSystem.outout.pri
17、ntln(main()println(main();SystemSystem.outout.println(carprintln(car.i i=+carcar.i)i);输出:输出:main()main()wheelwheel-2 2 wheelwheel-3 3 car.i=0car.i=0第1次创建对象时,类中所有的静态变量要初始化第1次访问类中的静态变量(没有创建对象)时,该类中所有的静态变量也要按照它们在类中排列的顺序初始化。classclass Wheel Wheel Wheel(String str)Wheel(String str)SystemSystem.out.printl
18、n(str);.out.println(str);例6-6126.1构造函数的执行机制:总结例63:在创建对象时,对象所在类的所有数据成员(包括对象)首先按顺序进行初始化,所有类成员初始化完成后,才调用对象所在类的构造方法创建对象。构造方法作用就是初始化。例6-4,6-5:静态对象(变量)在非静态对象前初始化。静态对象(变量)只初始化一次,再次调用就丌初始化了,但非静态对象在每次调用时都要初始化。2010/11/22010/11/27 7136.1构造函数的执行机制:总结例6-5:程序中的主类的静态变量会在main()方法执行前进行初始化工作。例66:丌仅第1次创建对象(如)时,类中所有的静态
19、变量要初始化,第1次访问类中的静态变量(没有创建对象)时,该类中所有的静态变量也要按照它们在类中排列的顺序初始化。14初始化的顺序包括构造方法调用顺序1.主类的静态成员首先初始化。2.主类的超类的构造方法按照从最高到最低的顺序被调用。3.主类的非静态对象(变量)初始化。4.调用主类的构造方法。class Car class Car extends Wheelextends Wheel(2 2)Wheel wheel_1=new Wheel(wheelWheel wheel_1=new Wheel(wheel-1);1);(3 3)Wheel wheel_2=new Wheel(wheelWhe
20、el wheel_2=new Wheel(wheel-2);2);static Wheel wheel_3=new Wheel(wheelstatic Wheel wheel_3=new Wheel(wheel-3);3);(1 1)Car(String str)Car(String str)(4 4)System.out.println(str);System.out.println(str);2010/11/22010/11/28 8156.2 屏蔽、覆盖和重载6.2.1 屏蔽子类可以直接从父类继承下来的属性和方法,就象是自己的一样。如果在子类中又声明了相同名称的属性,则称作子类的该属性屏
21、蔽(shadow)了父类中对应的属性。16publicpublic classclass ShadowTestShadowTest1 1 publicpublic staticstatic voidvoid main(Stringmain(String argv)argv)A A a a=newnew A()A();B B b b=newnew B()B();SystemSystem.outout.println(aprintln(a.i i=+a+a.i)i);SystemSystem.outout.println(bprintln(b.i i=+b+b.i)i);运行结果运行结果10101
22、0101010a.i=10a.i=10b.i=10b.i=10例67:B类只是单纯地继承了A类,所以显示出来的i值均为10。提问:为什么上面输出有3个10?class B extends Aclass B extends Apublic B()public B()System.out.println(i);System.out.println(i);classclass AAintint i=i=1010;publicpublic A()A()SystemSystem.outout.println(i)println(i);2010/11/22010/11/29 917publicpublic
23、 classclass ShadowTestShadowTest2 2 publicpublic staticstatic voidvoid main(Stringmain(String argv)argv)A A a a=newnew A()A();B B b b=newnew B()B();SystemSystem.outout.println(aprintln(a.i i=+a+a.i)i);SystemSystem.outout.println(bprintln(b.i i=+b+b.i)i);结果10105a.i=10b.i=5例6-8:类B中的属性i覆盖了类A中的i,显示出来的是自
24、身的值5。如果要在B类中显示A类的i值,可用super.i。classclass B B extendsextends AAintint i=i=5 5;/新增新增publicpublic B()B()SystemSystem.outout.println(i)println(i);classclass AAintint i=i=1010;publicpublic A()A()SystemSystem.outout.println(i)println(i);186.2.2 覆盖(override)与多态覆盖,这里是针对方法而言的。如果子类中定义方法所用的名字、返回类型和参数表和父类中方法使用的
25、完全一样,称子类方法覆盖了父类中的方法,即子类中的成员方法将隐藏父类中的同名方法。注意:覆盖的同名方法中,子类方法丌能比父类方法的访问权限更严格。在子类中,若要使用父类中被隐藏的方法,可以使用super关键字。正是利用方法的覆盖可以实现多态性。2010/11/22010/11/2101019classclass AnimalAnimalpublicpublic intint weightweight;publicpublic StringString colourcolour;publicpublic voidvoid eat()eat()SystemSystem.outout.println
26、(Eating)println(Eating);publicpublic voidvoid move()move()SystemSystem.outout.println(Iprintln(I amam Moving)Moving);class Dog extends Animalpublic void move()System.out.println(I am Running);class Bird extends Animalpublic void move()System.out.println(I am Flying);例6 6-9 920例6 6-9 9public class In
27、heritTest1public class InheritTest1publicpublic staticstatic voidvoid main(Stringmain(String argv)argv)AnimalAnimal a,aa,a1 1=newnew Animal()Animal();DogDog d d1 1=newnew Dog()Dog();BirdBirdb b1 1=newnew Bird()Bird();a=aa=a1 1;a a.move()move();a=da=d1 1;a a.move()move();a=ba=b1 1;a a.move()move();运行
28、结果为:I am MovingI am RunningI am Flying2010/11/22010/11/21111216.2.3 重载方法名如果需要在同一类中写多个方法,让它们对丌同的变量进行同样的操作,就需要重载方法名。现在假定需要打印int,float和String类型的值。每种类型的打印方式丌同,丌同的数据类型需要丌同的格式,可能要进行丌同的处理。此时可以建立三个方法,printint(),printfloat()和printString()。在Java和其他几种面向对象的程序设计语言中,允许对多个方法使用同一个方法名,这就是方法名的重载。前提条件:能区分实际调用的是哪个方法,才可
29、用这种方式。226.2.3 重载方法名实际上,Java根据参数的类型和参数自变量个数的丌同来调用适当的方法。public void print(int i)public void print(float f)public void print(String s)当调用print方法时,可根据自变量的类型选中相应的一个方法。在这个例子中,根据参数自变量的类型来区分这些方法。当然,我们也可以根据参数自变量个数的丌同来区分他们注意:丌能根据返回值类型的丌同来实现重载。2010/11/22010/11/21212236.2 屏蔽、覆盖和重载 屏蔽:对于父类和子类的属性而言 覆盖:对于父类和子类的方法而
30、言(子类中定义方法所用的名字、返回类型和参数表和父类中方法使用的完全一样)重载:对于同一个类的多个方法而言(它们使用同一个方法名,对丌同变量进行相同的处理)246.3 类型转换 类和类乊间的类型转换只能用在父类和子类间,丌能用在兄弟类,更丌能用在根本丌相关的两个类乊间。这样当我们在类乊间转来转去时,才丌会迷失了方向。类型转换的规则:子类向父类转换时,属于自动类型转换;而父类要转换成子类时,就必须要使用强制类型转换了。强制类型转换的语法就跟一般基本数据类型转换的语法一样,用小括号运算符配合要转换成的类来做转换的操作。2010/11/22010/11/21313256.3 类型转换例例6 6-10
31、 10 有有A A、B B、C C三个类三个类,B B和和C C类都继承了类都继承了A A类类。publicpublic classclass TtoTTtoT1 1 publicpublic staticstatic voidvoid main(Stringmain(String argv)argv)A Aa a1 1=newnew A()A();B Bb b1 1=newnew B()B();C Cc c1 1=newnew C()C();a a1 1=b=b1 1;a a1 1=c=c1 1;/自动类型转换自动类型转换b b1 1=(B)a=(B)a1 1;/强制类型转换强制类型转换 父
32、类父类 子类子类b b1 1=(B)c=(B)c1 1;/类型转换类型转换兄弟类之间兄弟类之间 结果:编译出错!“Invalid cast from C toB”,26例例6 6-1111publicpublic classclass TtoTTtoT2 2 publicpublic staticstatic voidvoid main(Stringmain(String argv)argv)A A a a1 1=newnew A()A();B B b b1 1=newnew B()B();C C c c1 1=newnew C()C();a a1 1=c=c1 1;b b1 1=(B)a=(
33、B)a1 1;编译时丌会有问题,但是程序在执行时就会产生“ClassCastException”。这种错误在编写程序时比较丌容易被发现,所以要非常的小心。丌论类怎样转换,一个对象当初是什么样的类,它永远会是那个类的对象。所以在属性的访问和方法的调用上,要注意在什么样的情况下,只能做什么样的处理。2010/11/22010/11/21414276.4 对象之间的比较运算 数字和数字乊间可以比较大小,进行比较运算,对象和对象乊间也有比较运算。丌过通常两个对象乊间丌会比较大小,而是比较两个对象是否相等。数字乊间的比较运算很简单也很明确,相等就是相等,丌相等就是丌相等。而两个对象相等可以用两种丌同的观
34、点来看待,一种观点是两个对象指的是丌是同一个,另一种观点是两个对象的内容是否相等。28对象比较:例对象比较:例6 6-1212publicpublic classclass StringEqualsStringEquals1 1 publicpublic staticstatic voidvoid main(Stringmain(String argv)argv)StringString strstr1 1=newnew String(Hello)String(Hello);StringString strstr2 2=newnew String(Hello)String(Hello);Str
35、ingString strstr3 3=newnew String(Java)String(Java);StringString strstr4 4=strstr1 1;SystemSystem.outout.println(strprintln(str1 1=str=str2 2);SystemSystem.outout.println(strprintln(str1 1=str=str3 3);SystemSystem.outout.println(strprintln(str1 1=str=str4 4);结果:结果:falsefalsefalsefalsetruetrue2010/11
36、/22010/11/2151529Java对象的equals方法Java中每个类一定都有equals这个方法。用来比较两个对象的内容是否相同。以例6-12为例,若要比较两个String类对象是否表示相同的字符串,就可以使用这个方法,假设有a、b两个相同类所产生出来的对象,那equals方法的使用方式如下:a.equals(b)戒b.equals(a)30比较两个对象内容是否相同:例6-13publicpublic classclass StringEqualsStringEquals2 2 publicpublic staticstatic voidvoid main(Stringmain(S
37、tring argv)argv)StringString strstr1 1=newnew String(Hello)String(Hello);StringString strstr2 2=newnew String(Hello)String(Hello);StringString strstr3 3=newnew String(Java)String(Java);StringString strstr4 4=strstr1 1;SystemSystem.outout.println(println(strstr1 1.equals(strequals(str2 2);SystemSystem.outout.println(println(strstr1 1.equals(strequals(str3 3);SystemSystem.outout.println(println(strstr1 1.equals(strequals(str4 4);结果:结果:TrueTruefalsefalsetruetrue2010/11/22010/11/2161631第六章:面向对象编程的深入讨论总结:1.构造函数的执行机制(6个例子)2.屏蔽,覆盖和重载(注意区分三个名次含义)3.类型的转换4.对象的比较运算
限制150内