《JAVA快速入门练习4.doc》由会员分享,可在线阅读,更多相关《JAVA快速入门练习4.doc(43页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第4章 实验 方法4.1实验目标(1) 了解类、对象、方法的根本概念,方法的参数含义。(2) 参数和变量的作用域,定义和使用静态方法。(3) 方法定义和调用,包括有返回值和无返回值的方法的定义和调用。(4) 了解JAVA根本类库中的一些与原始数据类型密切相关的一些方法。(5) 递归和迭代机制及函数实现。4.2实验说明本章实验教程将初步介绍JAVA类class、对象object和方法method的一些根本概念。以下的实验包括4种类型, 每种类型都用括号里面的字母表示:D - 例程, 表示这是一个例子, 要求练习者阅读指南和代码; I - 交互式练习, 练习者完成实验指定的简单任务,如修改局部代码
2、, 观察程序运行时的变化等; W - 热身练习, 练习者的编程工作量逐渐加大。P - 完整编程 ,要求练习者根据要求,完成完整的JAVA程序。4.3实验准备从本实验教程光盘中拷贝Lab04文件目录到本地磁盘, 如C: 盘。Lab04文件目录中将包含本次实验所需的所有资料。 Lab04的相关资料也可以从本实验教程的网站下载: :/javaLab/lab04.zip4.4实验任务实验4.4.1: (D)初步介绍JAVA类、对象和方法 1. 使用JAVA开发包中的类JAVA程序由类(class)组成,类中包含方法(method)。到目前为止,实验教程中涉及的程序只有一个类一个方法:在应用程序中的ma
3、in方法和在applet中的paint方法。程序中还用到了类的其他方法,这些方法不是我们自己编写的,它们是JAVA开发包中的一局部。例如使用类JOptionPane中的showMessageDialog和showInputDialog方法,无需编写整个代码,而是进行方法调用: JOptionPane.showMessageDialog(null, Hi there!); String name = JoptionPane.showInputDialog(Whats your name?);使用类JOptionPane中的方法,需要在程序的开头加上import语句: import javax.s
4、wing.JOptionPane;使用了import语句,编译器才能在JAVA类库中的javax.swing包中找到类JOptionPane。另外,类Integer的方法parseInt可以将为String表达形式的数字转化成int类型。使用类Interger中的方法不必写一个import语句。java.lang中的所有类包括类Integer都是自动导入到每一个Java程序之中的,程序不必显式地给出导入过程。要使用Java其他库包中的类那么需要显式地给出导入语句。 2. 简单理解一下Java对象和类的关系Java对象Object是计算机存储区中用来存储特定类型数据的一个区域,这些特殊类型的数据
5、是根据类Class来定义的。举个简单例子:程序清单4-1:Student.java/Student.javapublic class Student private int id; / 学生IDprivate String name; / 姓名public Student(int id, String name)this.id = id;this.name = name;public int getID() return id;public void setID(int id) this.id = id;public String getName() return name; public v
6、oid setName(String name) this.name = name;这里定义了一个Student类,它有2个属性、4个实例方法和1个构造方法。根据Student的数据结构,可以创立多个对象。类的对象也被称作是类的实例instance。3. JAVA的两种数据类型体系JAVA有两种数据类型:原始数据类型Primitive Data Type和引用数据类型Reference Data Type。原始数据类型在前面已经做过介绍,它的值就是一个数字、一个字符或一个布尔值。而身为引用数据类型的变量又被称为是对象引用,实际上它的值是指向内存空间的引用就是地址,该地址指向的内存中保存着变量所
7、表示的一个值或一组值。举个例子说明:Student s1, s2; / 在内存中分配两个引用数据类型变量的空间 s1 = new Student; / 分配Student对象的数据空间,并把该空间的首地址0xabcdef赋给s1s2 = s1; / 将s1存储空间中的地址复制到s2的存储空间中如图4.1所示:图4.1 引用数据类型举例 由于变量s1和s2的值相同,即指向同一个内存地址,s1和s2实际上是同一个对象。4. 类的三种方法method Java类有三种方法:构造方法constructor,实例方法instance method和静态方法static method。它们分别有不同的调用
8、方式。 (1) 构造方法constructor构造方法用于创立对象。对象在使用前必须要初始化,即为对象分配数据空间。调用构造方法创立一个Student对象: Student s = new Student(123, he xiang);注意到类的构造方法与类同名,调用构造方法通常使用关键字new。这里,首先为变量s分配一个引用空间;使用new关键字调用类的构造方法为Student类的对象分配数据空间;将数据空间的首地址赋给s。(2) 实例方法instance method 对象创立后,就可以让它做一些操作。为此,就要调用实例方法。实例方法定义了一个对象的行为,其调用的格式如下: 对象引用.方法
9、名(参数) objectReference.methodName(parameters)例如,调用Student对象s的getID方法: s.getID(); (3) 静态方法static method类JOptionPane的showMessageDialog和showInputDialog方法以及类Integer的parseInt方法的使用有一个相同点,其调用形式如下: 类名.方法名(参数) ClassName.methodName(parameters)以这种形式调用的方法称为静态方法static method。静态方法定义的行为并不针对某个特定的对象。注意这点与实例方法的不同。另外,静
10、态方法的方法头有关键字static,实例方法和构造方法没有此关键字。实验4.4.2: (D)方法的参数 Applet中的paint方法有如下的方法头定义: public void paint(Graphics g)扩符( ) 中的g是声明为Graphics类型的变量。在方法头的扩符内声明的变量被称为是形式参数。形式参数不需要初始化,因为方法调用时它(们)已经被自动地赋值。在paint方法中,可以假设变量g已经指向了类Graphics的一个对象了。在paint方法里,可以使用已经存在的Graphics对象来画图,比方调用方法drawString和drawLine。 下面的语句对Font类作了如下
11、的实例化: Font ft= new Font(Serif, Font.PLAIN, 56); g.setFont(ft);第一句调用了一个构造方法来创立一个对象,此对象被变量ft引用。在第二句中,我们没有调用Font对象ft的实例方法。而是将ft作为参数传递给setFont方法,此方法为Graphics对象g的一个实例方法。 Java库中,类Graphics方法setFont的方法头定义如下: public abstract void setFont(Font font)这里的形式参数font在setFont方法调用时自动接收实例化的Font对象ft为它的实际值。形式参数接收的实际值被称为实
12、际参数。在上面的例子中,实际参数是ft。类似地,main方法有类型为String(字符串数组)的形式参数: public static void main(String args)实验4.4.3: (D)变量及其作用域1. Java有四种类型的变量:本地变量local variable、实例变量instance variable、类变量class variable和参数parameter。 本地变量在方法中声明;实例变量和类变量在类体中、方法体外声明。实例变量和类变量看起来比拟类似,只是类变量是静态变量,使用static访问修饰符。Java虚拟机JVM在方法或构造方法执行前为参数分配空间,并在
13、消息处理完成后释放空间。下面是Java类中声明变量的一般形式的伪代码pseudocode: class someClass visibility_modifier variable_type instanceVariableName; / Instance Variable visibility_modifier static variable_type classVariableName; / Class Variable returnType someMethod1() variable_type localVariableName; / Local Variable returnType
14、 someMethod2(Type parameterName) / Parameter instanceVariableName和classVariableName 在someClass类体中声明,其中instanceVariableName是实例变量,classVariableName是类变量;localVariableName在someMethod方法中声明,是本地变量。parameterName是方法someMehod2的形式参数简称“形参。2. 变量是数据的标识。上面的伪代码中变量名分别是:instanceVariableName, classVariableName, localV
15、ariableName和parameterName。变量名必须是合法的标识符,具体的要求如下:(1) 不能使用保存字;(2) 是字母、数字、美元符号“$或下划线“_的序列;(3) 不能以数字开头,必须以字母、美元符号“$或下划线“_开头;(4) 区分大小写,比方myName和MyName是不同的标识符。合法的变量名如:x、value-1、$amount等;非法的变量名如:2brother、room#、class(保存字)等。就象给家里的每个孩子取不同名字,变量名应具有一定的含义,以增加程序的可读性。3. 变量的声明声明变量将在存储器中分配一定的空间,用于存储相应类型的数据,稍后可以使用变量名访
16、问存储在该空间的数据。注意,变量声明仅仅为变量分配内存空间,并没有实际地存储数据。Java语言是一种强类型语言,即声明时必须指定变量的数据类型,编译器为其分配相应的存储空间。有强类型语言,就有弱类型语言,比方VB、JAVASCRIPT编程语言,弱类型不一定需要指定数据类型,编译器会用相同的空间去分配各种类型。变量的声明格式为: type identifier =value ,identifier=value;以下是有效的变量声明:int id;String name;4. 变量的作用域Java中具体有以下四种类型的作用域:成员变量作用域、本地变量作用域、参数作用域以及异常处理参数作用域。图4.
17、2 Java变量作用域如图4.2所示,成员变量包括类变量和实例变量。它们在类中定义,而不是在任何方法或者构造方法中定义。成员变量的作用域是整个类体。本地变量的作用域从该变量声明开始到定义此变量的代码块结束为止。参数是指方法或构造方法的形式参数,用于传递数值给方法或构造方法。参数的作用域是整个方法或构造方法。异常处理参数跟参数相似,差异在于前者是传递参数给异常处理,而后者是传递给方法或构造方法。异常处理参数的作用域处在catch 和之间。见下面的代码:if (.) int i = 17;.System.out.println(The value of i = + i); / 错误代码最后一行无法
18、汇编,因为if块中定义的本地变量i已经超出作用域。改正的方法是,将变量声明移到if语句块的外面,或者将println语句移动到if语句块中。5. 变量的的生命周期 不同变量有不同作用域,作用域定义了变量在程序内存中的生命周期。变量一旦离开其作用域,它所占的内存空间就会被Java虚拟机JVM标注为可垃圾回收,变量就无法被引用了。 本地变量必须在方法中声明。这当然也包括方法中嵌入的代码块,如if、while或for代码块。变量在它所声明的代码块中是本地的。例如,方法体中声明的变量在此方法中是本地变量,在if块中声明的变量在此if块中是本地变量。这意味着在花括号中声明的变量在花括号外不能使用。 实例
19、变量是对象的组成局部,每个对象的实例都有属于自己的实例变量。例如,Order类中声明了一个名为orderDate的实例变量,那么Order类的每个对象都有自己的orderDate,可以为自己的orderDate设定不同的值。实例变量不能离开对象独立存在,因此,实例变量与包含它的对象的生命周期相同。类变量的生存周期是从该类被JVM加载开始到释放该类结束。当类第一次被引用时通常情况是用new实例化类的第一个对象,类被加载到JVM。类变量类似与全局变量,它的生存周期在变量中是最长的。类变量被该类的所有对象共享,所以如果有十个Order对象,那么类变量todayDate的值被十个对象共享,事实上,所有
20、Order对象访问的是同一个todayDate。6. 编译、运行VariableScope.java程序,仔细阅读代码中的注释,理解Java各种变量的使用。程序清单4-2:VariableScope.java/VariableScope.javapublic class VariableScope/ classVariableName类变量的作用域是整个类体static public String classVariableName = 类变量; / instanceVariableName实例变量的作用域是整个类体private int instanceVariableName = 0; /
21、 参数intParameter 的作用域是整个oneMethod方法体public void oneMethod(int intParameter) / 局部变量temp的作用域都是整个oneMethod方法体int temp=5;if(intParameter temp)/ 在不同作用域声明同名变量,在JAVA中是不允许的,下边的语句会报错/ int temp = 1; System.out.println(方法内部可以访问局部变量,局部变量temp = + temp);instanceVariableName = instanceVariableName + intParameter;pu
22、blic void anotherMethod()System.out.println(类变量是 + classVariableName);System.out.println(实例变量instanceVariableName = + instanceVariableName);public static void main(String args)/ 创立一个VariableScope对象/ JVM载入VariableScope类,classVariableName生命周期开始VariableScope object1=new VariableScope();/ 可以通过类名或对象名访问Va
23、riableScope类的静态变量,例如:System.out.println(使用类名访问 + VariableScope.classVariableName);System.out.println(使用对象名访问 + object1.classVariableName);/ object1对象的实例变量instancevariable1,instancevariable2生命周期开始object1.oneMethod(6);object1.anotherMethod(); / object1对象的实例变量instanceVariableName生命周期结束实验4.4.4: (I)定义和使用
24、静态(static)方法1. 先回忆一下这段Hello.java程序: public class Hello public static void main(String args) System.out.println(Hello,world!); 注意这里static关键字的用法。程序定义了一个静态的方法名为main,这意味着告诉Java编译器,此方法无需创立一个Hello类的对象即可调用。简单理解static:static - 静态 内存中指定位置 用static修饰的变量和方法,实际上是指定了这些变量和方法在内存中分配有“固定位置和“固定大小。 static变量有点类似于C中的全局变量
25、的概念;静态表示了内存的共享,即此类的所有对象都可以操控此块存储空间。2. 编译DrawX.java (见程序清单4-3),编写相应的ViewDrawX.html文件运行程序。注意在运行DrawX.java之前要先编译GraphicsUtility.java见程序清单4-4。程序清单4-3:DrawX.java/ DrawX.java/ Draws 3 big Xs./ 使用类GraphicsUtility的一个方法来画每一个X.import java.applet.Applet;import java.awt.Graphics;import java.awt.Color;public cla
26、ss DrawX extends Applet public void paint(Graphics pen) setBackground(Color.black); pen.setColor(Color.white); GraphicsUtility.drawX(pen, 0, 0); GraphicsUtility.drawX(pen, 4, 0); GraphicsUtility.drawX(pen, 29, 35); / method paint(Graphics) / class DrawX.java窗口小程序显示三个“X。观察DrawX.java 和GraphicsUtility.
27、java源程序。注意到DrawX.java 中并没有使用画直线的drawLine方法,而是调用了GraphicsUtility类中定义的drawX方法。GraphicsUtility类中的drawX方法可以在指定位置画出一个X,方法定义如下: public static void drawX(Graphics g, int x, int y) g.drawLine(x, y, x+200, y+130); g.drawLine(x, y+130, x+200, y); / method drawX(Graphics, int, int)方法的定义包含方法名和方法体。drawX的方法名为: pu
28、blic static void drawX(Graphics g, int x, int y)圆括号( )中包含了此方法的多个形式参数及其数据类型。方法体为花括号 里包含的代码。程序清单4-4:GraphicsUtility.javaimport java.awt.Graphics;public class GraphicsUtility public static void drawX(Graphics g, int x, int y) g.drawLine(x, y, x+200, y+130); g.drawLine(x, y+130, x+200, y); / method draw
29、X / class GraphicsUtility对一个方法的使用,称为调用call。类DrawX中的paint方法三次调用了类GraphicsUtility中的 drawX方法: GraphicsUtility.drawX(pen, 0, 0); GraphicsUtility.drawX(pen, 4, 0); GraphicsUtility.drawX(pen,29, 35);在三个不同位置上画出三个“X。在调用drawX 方法时,形式参数被自动初始化为实际参数。例如, paint方法中第一次调用drawX时,Java虚拟机执行如下等效语句: Graphics g = pen; int
30、x = 0; int y = 0;用于接收传递值的变量称为形式参数(formal parameter);被传递给方法的值称为实际参数actual parameter。因为形式参数在方法调用时被自动赋值,所以在方法体内不需要初始化。在方法体中声明的变量叫做本地变量local variable。与形式参数不同,本地变量必须在方法体内初始化。 注意GraphicsUtility 既不是一个application 也不是一个applet。 它不包含main方法也不包含 “extends Applet。修改DrawX.java程序中调用drawX方法的实际参数值,重新编译和运行程序,观察“X在窗口中位置
31、的变化。3. 练习写一个静态方法。 为类GraphicsUtility 写一个新方法drawZ,这个方法和drawX 相似,只是前者画“Z后者画“X。GraphicUtility.java 现在包含两个方法:方法drawZ和方法drawX。方法drawZ应该以以下语句作为开头: public static void drawZ(Graphics g, int x, int y)其中x和y为所画“Z的左上角。“Z的大小为20像素宽、30像素高。 编写DrawXZ.java,通过调用类GraphicsUtility的方法drawZ和方法drawX来显示两个Z和一个X。在一个宽201像素和高110像
32、素的applet显示屏HTML文件ViewDrawXZ.htmlz中规定的上,两个Z的左上角位置相为0,0和180,0,X的左上角位置为90,50。 程序清单4-5:ViewDrawXZ.html A simple applet 此applet将画一些X和Z。能很好地工作?定义方法drawZ时,注意方法体前后都有花括号,同时确定方法drawZ是定义在类GraphicsUtility 中。 实验4.4.5: (D)有返回值的方法1. 观察MathUtility.java程序源代码。程序清单4-6:MathUtility.java/MathUtility.javapublic class Math
33、Utility public static double power(float base, int exponent) if ( exponent 0 ) exponent = 0 - exponent;base = 1 / base; / if exponent 0double product = 1;for ( int i = 0; i exponent; i+ )product *= base;return product; / method power(float, int)public static long power(int base, int exponent) if (ex
34、ponent 0) System.err.println(错误: MathUtility.power(int, int) + 不能处理指数 + exponent + 0.);System.err.println(要求非负指数 + 返回长整型值。);return 0; / if exponent 0long product = 1;for ( int i = 0; i exponent; i+ )product *= base;return product; / method power(int, int) / class MathUtility注意到程序中包含有两个power方法。虽然这些方法
35、有相同的名字,但方法头中定义的形式参数却不一样。其中一个power方法的两个参数为类型float和类型int,另外一个power方法的参数都为类型int。Java 中,同一个类中的2个或2个以上的方法可以有同一个名字,只要它们的参数声明不同即可。这种方法定义称为“方法重载method overload。当调用一个重载方法时,虚拟时机根据不同的参数样式来选择适宜的方法执行。不同的参数样式是指参数的类型和或数量不同。2. MathUtility.java的两个power方法不仅参数样式不同,它们的返回值也不同。方法的返回值在方法头中确定。第一个power方法返回一个double值,第二个power
36、方法返回一个long型的值。 编译运行程序PowerTest1.java。程序源代码见程序清单4-7。程序清单4-7:PowerTest1.java/ PowerTest1.java/ Tests the two power methods/ in class MathUtilitypublic class PowerTest1 public static void main(String args) final int intBase = 2; final int exponent = 50; final float floatBase = intBase; long longPower =
37、 MathUtility.power(intBase, exponent); double doublePower = MathUtility.power(floatBase, exponent); System.out.println(); / blank line System.out.println(intBase + 上调为 + exponent + 时指数是:); System.out.println(); System.out.println( + longPower + (long); System.out.println( + doublePower + (double unf
38、ormatted); / method main / class PowerTest1 程序分别调用类MathUtility的两种power方法计算2的50次方,并以非格式化方式显示double类型的运算结果。非格式化的double数值,以科学记数法显示,如下: 1.125899906842624E15意为 1.125899906842624 乘上10 的15次方。比拟大的浮点数float或double都默认采用科学记数法表示。浮点数在内存中的存储也类似科学记数方式,只是它涉及的指数为2而非10。PowerTest1.java中调用类MathUtility的power方法: long long
39、Power = MathUtility.power(intBase, exponent); double doublePower = MathUtility.power(floatBase, exponent);这两个power方法产生各自的返回值,并分别赋值给longPower和doublePower。这类似数学中的函数: y = f(x) z = g(x, y)Java中的“方法,在其他编程语言中被称为“函数。在Pascal中,有返回值的子程序称为“函数,没有返回值的子程序称为“过程。在C和C+中,所有子程序不管是否有返回值,统称为“函数。有返回值的方法在开头要声明返回类型,而且以一个返回
40、语句作为结束。例如,类MathUtility的两个power方法都以: return product;结束。有返回值的方法中,返回语句包含return关键字以及返回值的表达式。在这个例子中,每一个power方法返回变量product。 3. 看一下计算指数的算法: for ( int i = 0; i exponent; i+ ) product *= base;类MathUtility的两个power方法中处理负数指数的方式不同。编译并运行PowerTest2.java看两个方法是如何处理负数指数的。程序清单4-8:PowerTest2.java/ PowerTest2.java/ Test
41、s the two power methods/ in class MathUtilitypublic class PowerTest2 public static void main(String args) final int intBase = 2; final int exponent = -3; final float floatBase = intBase; long longPower = MathUtility.power(intBase, exponent); double doublePower = MathUtility.power(floatBase, exponent
42、); System.out.println(); / blank line System.out.println(intBase + 调整为 + exponent + 时指数为:); System.out.println(); System.out.println( + longPower + (long); System.out.println( + doublePower + (double); System.out.println(); / method main / class PowerTest2 注意到数x的负指数是值为1/x的正指数。所以在浮点版本的power方法中,如果expo
43、nent是负数,那么首先将其替换为相应的正数指数形式。而整数版本的power方法中,如果exponet为负数的话,将产生一个错误消息并返回0值。 错误消息通过System.err打印出,System.err为标准错误流,而不是通过标准输出流System.out输出。System.out和System.err都可以通过DOS窗口显示。4. PowerTest3.java程序除main方法外,还包含一个静态方法testPower以完成实际的测试。程序清单4-9:PowerTest3.java/ PowerTest3.java/ Tests the two power methods/ in class MathUtilitypublic class PowerTest3 public static void main(String