资源预览内容
第1页 / 共156页
第2页 / 共156页
第3页 / 共156页
第4页 / 共156页
第5页 / 共156页
第6页 / 共156页
第7页 / 共156页
第8页 / 共156页
第9页 / 共156页
第10页 / 共156页
亲,该文档总共156页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
第4章 类与对象 第4章 类与对象 4.1 类与对象的概念类与对象的概念 4.2 封装机制封装机制 4.3 数据成员数据成员 4.4 成员方法成员方法 第4章 类与对象 4.1 类与对象的概念类与对象的概念程序设计所面对的问题域客观世界,是由许多事物构成的,这些事物既可以是有形的(比如一辆汽车),也可以是无形的(比如一次会议)。在面向对象的程序设计中,客观世界中的事物映射为对象。对象是面向对象程序设计中用来描述客观事物的基本单位。客观世界中的许多对象,无论其属性还是其行为常常有许多共同性,抽象出这些对象的共同性便可以构成类。所以,类是对象的抽象和归纳,对象是类的实例。第4章 类与对象 4.1.1 抽象原则抽象原则所谓抽象(abstraction),就是从被研究对象中舍弃个别的、非本质的,或与研究主旨无关的次要特征,而抽取与研究工作有关的实质性内容加以考察,形成对所研究问题正确的、简明扼要的认识。例如,“马”就是一个抽象的概念,实际上没有任何两匹马是完全相同的,但是我们舍弃了每匹马个体之间的差异,抽取其共同的、本质性的特征,就形成了“马”这个概念。第4章 类与对象 抽象是科学研究中经常使用的一种方法,是形成概念的必要手段。在计算机软件开发领域,所有编程语言都提供抽象机制,人们所能够解决的问题的复杂性直接取决于抽象的层次和质量。编程语言的抽象是指求解问题时是否根据运行解决方案的计算机结构来描述问题,它是以“机器语言汇编语言面向过程的语言面向对象的语言”这样的路径发展的。随着不同抽象层次的进展,目前主要强调的是过程抽象和数据抽象。第4章 类与对象 1. 过程抽象过程抽象过程抽象(procedural abstraction)是指任何一个完成确定功能的操作序列,其使用者都可把它看做一个单一的实体,尽管这个操作可能是由一系列更低级的操作完成的。过程抽象隐藏了过程的具体实现。例如,用于求一个正整数平方的过程可以有下面的不同实现方式。方式1:int square(int k) return k*k; 第4章 类与对象 方式2:int square(int k) int result=0;for(int i=0; iy?x:y);if(xy) return true;else return(false);都是合法的,且“return z;”与“return(z);”等价。第4章 类与对象 4.4.5 形式参数与实际参数形式参数与实际参数一般来说,可通过如下的格式来引用成员方法:成员方法名(实参列表)但在引用时应注意下述问题:(1) 对于无参成员方法来说,是没有实参列表的,但方法名后的括号不能省略。(2) 对于带参数的成员方法来说,实参的个数、顺序必须与形式参数的个数、顺序保持一致,实参的数据类型与形参的数据类型按照Java类型转换规则匹配,各个实参间用逗号分隔。实参名与形参名可以相同也可以不同。第4章 类与对象 (3) 实参可以是表达式,此时要注意使表达式的数据类型与形参的数据类型按照Java的类型转换规则匹配。(4) 实参变量(基本数据类型变量)对形参变量的数据传递是“值传递”,即只能由实参传递给形参,而不能由形参传递给实参。程序中执行到引用成员方法时,Java把实参值拷贝到一个临时的存储区(栈)中,形参的任何修改都在栈中进行,当退出该成员方法时,Java自动清除栈中的内容。下面我们通过一个程序来说明上述各点。第4章 类与对象 【示例程序C4_12.java】 实际参数与形式参数的传递使用1。public class C4_12 static void add(double x,double y) double z; z=x+y; System.out.println(“z=”+z); x=x+3.2;y=y+1.2; System.out.println(“x=”+x+“ty=”+y); 第4章 类与对象 static double add1(double y1,double y2) double z; z=y1+y2+2.9; return z; public static void main(String args) int a=2,b=7; double f1=2,f2=4,f3; add(a,b);/按Java的类型转换规则达到形参类型 System.out.println(a=+a+tb=+b); / f3=add1(f1, f2, 3.5); 错,实参与形参的参数个数不一致 f3=2+add1(f1,f2);第4章 类与对象 System.out.println(“f1=”+f1+“tf2=”+f2+“tf3=”+f3); 该程序的运行结果如下:z=9.0x=5.2 y=8.2a=2 b=7f1=2.0 f2=4.0f3=10.9第4章 类与对象 【示例程序C4_13.java】 实际参数与形式参数的传递使用2。public class C4_13 static void add(double x,double y) double z; z=x+y; System.out.println(“z=”+z); static double add1(double y1,double y2) double z; z=y1+y2+2.9; return z; 第4章 类与对象 public static void main(String args) int a=2; double f1=2,f2=4; add(a,add1(f1,f2); 该程序的运行结果如下:10.9第4章 类与对象 4.4.6 成员方法的引用方式成员方法的引用方式成员方法的引用可有下述几种方式。1方法语句方法语句成员方法作为一个独立的语句被引用。例如,程序C4_12.java中的“add(a,b);”语句就是这种形式。2方法表达式方法表达式成员方法作为表达式中的一部分,通过表达式被引用。例如,程序C4_12.java中的“f3=2+add1(f1,f2);”语句就是这种形式。第4章 类与对象 3方法作为参数方法作为参数一个成员方法作为另一个成员方法的参数被引用。例如,程序C4_13.java中的“add(a,add1(f1,f2);”语句就是这种形式的代表。更为典型的是,在递归的成员方法中,一个成员方法作为它自身的参数被引用。4通过对象来引用通过对象来引用这里有两重含义,一是通过形如“引用变量名.方法名”的形式来引用与之关联的对象的方法。二是当一个对象作为成员方法的参数时,通过把与之关联的引用变量作为参数来引用对象的成员方法。例如,程序C4_3.java中的“dane.showDog(g,25,25);”语句,成员方法showDog()本身通过引用变量dane来引用对象的方法;同时,通过作为参数的引用变量g引用Graphics类的对象的成员方法drawString()。第4章 类与对象 4.4.7 引用成员方法时应注意的事项引用成员方法时应注意的事项首先,当一个方法引用另一个方法时,这个被引用的方法必须是已经存在的方法。除了这个要求之外,还要视被引用的成员方法存在于何处而做不同的处理。(1) 如果被引用的方法存在于本文件中,而且是本类的方法,则可直接引用。我们前面列举的例子基本上都是这种情况。(2) 如果被引用的方法存在于本文件中,但不是本类的方法,则要由类的修饰符与方法的修饰符来决定是否能引用。第4章 类与对象 (3) 如果被引用的方法不是本文件的方法而是Java类库的方法,则必须在文件的开头处用import 命令将引用有关库方法所需要的信息写入本文件中。例如,前几章用来在屏幕指定位置上显示一个字符串的drawString() 方法是Java类库Graphics类中的一个方法,而Graphics类存放在java.awt包中,因此,我们在程序文件的开头处写上了“import java.awt.*;”语句,指出awt包中的方法在本文件中要引用。(4) 如果被引用的方法是用户在其他的文件中自己定义的方法,则必须通过加载用户包的方式来引用。这部分内容将在5.5节“接口与包”中讲述。第4章 类与对象 4.4.8 成员方法的递归引用成员方法的递归引用我们前面讲述的程序都以严格的层次方式在一个方法中调用另一个方法。但是,对于某些实际问题,方法调用自身会使程序更为简洁清晰,而且会使程序的执行逻辑与数理逻辑保持一致。例如,数学中对于N!的定义是:第4章 类与对象 这个定义是递归的,即在N!=N(N-1)! 中,(N-1)!实际上是N!的减1递推。对于这样的问题,我们可以构造循环来求解,即用123(n-1)n的算式求得结果。但是,由于它的定义本身是递归的,用递归算法实现则更符合数理逻辑。例如,求4!的过程可表示成图4.13所示的形式。第4章 类与对象 图4.13 求4!的递归过程 第4章 类与对象 成员方法的递归引用就是指在一个方法中直接或间接引用自身的情况。例如:第4章 类与对象 在这个例子中,方法f1()中引用了f1()本身,这种引用是直接引用。第4章 类与对象 在这个例子中,方法f1()在引用方法f2()的过程中,又引用了方法f1()本身;同样,方法f2()在引用方法f1()的过程中,又引用了方法f2()本身,这种引用是间接引用。第4章 类与对象 【示例程序C4_14.java】 编程计算4!的值。public class C4_14 static int fac(int n) int fa; if(n=0) fa=1; else fa=n*fac(n-1); /递归引用自身 return fa; 第4章 类与对象 public static void main(String args) int n=4; int f1=fac(n); /引用fac()方法 System.out.println(“4!=”+f1); 该程序的运行结果如下:4!=24该程序中fac()方法的递归引用如图4.14所示。第4章 类与对象 图4.14 计算4!的成员方法fac的递归引用关系 第4章 类与对象 从图中可以看到,求4!时,main方法引用fac(4)方法,fac(4)引用fac(3),fac(3)引用fac(2),fac(2)引用fac(1),fac(1)引用fac(0),fac(0)方法得到确定值1,回归得到fac(1)=1,再回归得到fac(2)=2,再回归得到fac(3)=6,最后再回归得到fac(4)=24,fac()方法共被引用了5次。第4章 类与对象 【示例程序C4_15.java】 编程求出Fibonacci数列的第8项。public class C4_15 public static void main(String args) int n=8; int f8=fibo(n); System.out.println(“f8=”+f8);第4章 类与对象 static int fibo(int n) if(n=1)return 1; else if(n=2)return 1; else return (fibo(n-1)+fibo(n-2); 该程序的运行结果如下:f8=21第4章 类与对象 4.4.9 用用static修饰的静态方法修饰的静态方法用static修饰符修饰的方法被称为静态方法,它是属于整个类的类方法。不用static修饰符限定的方法,是属于某个具体类的对象的方法。static方法使用特点如下:(1) static方法是属于整个类的,它在内存中的代码段将随着类的定义而被分配和装载。而非static的方法是属于某个对象的方法,当这个对象创建时,在对象的内存中拥有这个方法的专用代码段。(2) 引用静态方法时,可以使用与对象关联的引用变量名作为前缀,也可以使用类名作为前缀。第4章 类与对象 (3) static方法只能访问static数据成员,不能访问非static数据成员,但非static方法可以访问static数据成员。(4) static方法只能访问static方法,不能访问非static方法,但非static方法可以访问static方法。(5) static方法不能被覆盖,也就是说,这个类的子类不能有相同名及相同参数的方法。(6) main方法是静态方法。在Java的每个Application程序中,都必须有且只能有一个main方法,它是Application程序运行的入口点。第4章 类与对象 例如:class F int d1; static int d2; void me() static void me1() static void me2() me1(); /合法引用 d1=34; /错,引用了非static数据成员 me(); /错,引用了非static方法 d2=45; /合法 第4章 类与对象 class F1 extends F void me1() /错,不能覆盖类的方法第4章 类与对象 4.4.10 数学函数类方法数学函数类方法作为static方法的典型例子,我们来看看Java类库提供的实现常用数学函数运算的标准数学函数方法,这些方法都是static方法。标准数学函数方法在java.lang.Math类中,使用方法比较简单,其格式如下:类名.数学函数方法名(实参列表)java.lang.Math类提供的数学函数方法见表4.2。第4章 类与对象 表表4.2 java.lang.Math类提供的数学函数方法类提供的数学函数方法 第4章 类与对象 第4章 类与对象 【示例程序C4_16.java】 数学函数类方法的使用。public class C4_16 public static void main(String args) double a=2,b=3; double z1=Math.pow(a,b); /引用Math类的pow方法求a的b次方 double z2=Math.sqrt(9); /引用Math类的sqrt方法求9的平方根 System.out.print(“z1=”+z1); System.out.println(“tz2=”+z2); 该程序的运行结果如下:z1=8.0 z2=3.0第4章 类与对象 4.4.11 用用final修饰的最终方法修饰的最终方法在面向对象的程序设计中,子类可以利用重载机制修改从父类那里继承来的某些数据成员及成员方法。这种方法在给程序设计带来方便的同时,也给系统的安全带来了威胁。为此,Java语言提供了final修饰符来保证系统的安全。用final修饰符修饰的方法称为最终方法,如果类的某个方法被final修饰符所限定,则该类的子类就不能覆盖父类的方法,即不能再重新定义与此方法同名的自己的方法,而仅能使用从父类继承来的方法。可见,使用final修饰方法,就是为了给方法“上锁”,防止任何继承类修改此方法,以保证程序的安全性和正确性。第4章 类与对象 注意:在4.2.3节中我们已经讲过,final修饰符也可用于修饰类,而当用final修饰符修饰类时,所有包含在final类中的方法,都将自动成为final方法。【示例程序C4_17.java】 final修饰方法的使用。class A1 final int add(int x,int y) /用final修饰符修饰的最终方法 return(x+y); int mul(int a,int b) int z; z=add(1,7)+a*b; return z; 第4章 类与对象 public class C4_17 extends A1 /类C4_17是类A1的子类 /* int add(int x,int y) return(x+y+2); 子类C4_17企图覆盖父类A1的final方法,这是非法的 */ public static void main(String args) int a=2,b=3,z1,z2; C4_17 p1=new C4_17(); z1=p1.add(a,b); /子类可以引用父类的final方法 z2=p1.mul(a,b);第4章 类与对象 System.out.println(“z1=”+z1); System.out.println(“z2=”+z2); 该程序的运行结果如下:z1=5 z2=14第4章 类与对象 4.4.12 用用native修饰的本地方法修饰的本地方法用修饰符native修饰的方法称为本地方法,使用此类方法的目的是将其他语言(例如C、C+、FORTRAN、汇编语言等)嵌入到Java语言中。这样,Java就可以充分利用已经存在的其他语言的程序功能模块进行编程,以提高编程效率。第4章 类与对象 在Java程序中使用native方法时应该特别注意平台问题。由于用native方法嵌入的用其他语言书写的模块是以非Java字节码的二进制代码形式嵌入Java程序的,而这种二进制代码通常只能运行在编译生成它的平台之上,因此整个Java程序的跨平台性能将受到限制或破坏,除非native方法引入的代码也是跨平台的。有关的详细内容本书不再介绍,有兴趣者请参阅Java手册。
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号