1、本章主要介绍编写Java程序必须了解的若干语言基础知识,包括Java程序的结构、数据类型、变量、常量、表达式和流程控制语句等。掌握这些基础知识,是书写正确的Java程序的前提条件。3.1 Java程序的构成 上一章中已经介绍了几个简单的Java程序的例子,通过它们可以了解Java程序的一般构成规则,下面仍以例2-5中的程序为例,介绍Java程序的构成。AppletInOut.java 1:import java.applet.*;2:import java.awt.*;3:import java.awt.event.*;4:public class AppletInOut extends Ap
2、plet implements ActionListener 主类类头5:父类6:Label prompt;7:TextField input,output;静态属性8:9:public void init()10:11:prompt=new Label(请输入您的名字:);12:input=new TextField(6);13:output=new TextField(20);14:add(prompt);15:add(input);16:add(output);17:input.addActionListener(this);方法118:19:public void actionPerf
3、ormed(ActionEvent e)20:21:output.setText(input.getText()+,欢迎你!);22:方法223:主类类体Java源程序是由类定义组成的,每个程序中可以定义若干个类,但是只有一个类是主类。在Java Application中,这个主类是指包含main方法的类;在Java Applet里,这个主类是一个系统类Applet的子类。主类是Java程序执行的入口点。同一个Java程序中定义的若干类之间没有严格的逻辑关系要求,但它们通常是在一起协同工作的,每一个类都可能需要使用其他类中定义的静态属性或方法。Java程序中定义类使用关键字class,每个类的
4、定义由类头定义和类体定义两部分组成。类体部分用来定义静态属性和方法这两种类的成员,其中方法类似于其他高级语言中的函数,而静态属性则类似于变量。类头部分除了声明类名之外,还可以说明类的继承特性,当一个类被定义为是另一个已经存在的类(称为这个类的父类)的子类时,它就可以从其父类中继承一些已定义好的类成员而不必自己重复编码。语句是构成Java程序的基本单位之一。每一条Java语句都由分号(;)结束,其构成应该符合Java的语法规则。类和方法中的所有语句应该用一对大括号括起。Java程序是由类定义组成的,每个类内部包括类的静态属性声明和类的方法两部分,所以除了静态属性声明语句之外,其他的执行具体操作的
5、语句只能存在于类方法的大括号之中,而不能跳出方法孤立地直接书写在类中。例如,例2-5中第1117句、第21句,这些语句都不能写在方法的外面。比语句更小的语言单位是表达式、变量、常量和关键字等,Java的语句就是由它们构成的。其中变量与常量关键字是Java语言语法规定的保留字,用户程序定义的常量和变量的取名不能与保留字相同。3.2 数据类型、变量与常量 3.2.1 数据类型表3.1列出了Java中定义的所有数据类型,可以看出Java的数据类型的设置与C语言相近。其不同之处在于:首先,Java的各种数据类型占用固定的内存长度,与具体的软硬件平台环境无关;其次,Java的每种数据类型都对应一个缺省的
6、数值,使得这种数据类型的变量的取值总是确定的。这两点分别体现了Java的跨平台特性和安全稳定性。表3.1 Java的基本数据类型数据类型关键字占用位数缺省数值取值范围布尔型boolean8falsetrue,false字节型byte80-128127字符型char16u 0000u 0000 u FFFF短整型short160-3276832767整型int320-2147483648 2147483647长整型long640-92233720368547758089223372036854775807浮点型float320.0F1.40129846432481707e-453.4028234
7、6638528860e+38 双精度型double640.0D4.94065645841246544e-3241.79769313486231570e+308d boolean是用来表示布尔型数据的数据类型。boolean型的变量或常量的取值只有true和false两个。其中,true代表“真”,false代表“假”。byte是用来处理未经加工的二进制数据的数据类型,每个byte型的常量或变量中包含8位(bit)的二进制信息。Java的字符数据类型char与其他语言相比有较大的改进。C语言等的字符类型是采用ASCII编码,每个数据占用8比特的长度,总共可以表示256个不同的字符。ASCII编码
8、是国际标准的编码方式,但是也有其一定的局限性,最典型的体现在处理以汉字为代表的东方文字方面。汉字的字符集大,仅用8位编码是不够的,所以传统的处理方法是用两个8位的字符数据来表示一个汉字。为了简化问题,Java的字符类型采用了一种新的国际标准编码方案Unicode编码。每个Unicode码占用16个比特位,包含的信息量比ASCII码多了一倍,无论东方字符还是西方字符,都可以统一用一个字符表达。由于采用Unicode编码方案,为Java程序在基于不同语言的平台间实现平滑移植铺平了道路。上面所介绍的数据类型都是基本数据类型,Java中还存在着一种引用数据类型(reference),包括类和接口等。比
9、如,对应基本的double类型,还存在着一个类Double。这些类在包含基本数据类型所表示的一定范围、一定格式的数值的同时,还包含了一些特定的方法,可以实现对数值的专门操作,如把字符串转换成双精度型数值等。严格的面向对象语言中不应该有基本数据类型存在;但事实上这些简单数据类型应用得太广太多了,为了简化编程,Java中就定义了与面向过程语言相似的与类无关的基本数据类型。从这个意义上来说,Java仍继承了面向过程的一些东西,并不是严格意义上的完全面向对象的语言。3.2.2 标识符 任何一个变量、常量、方法、对象和类都需要有一个名字标志它的存在,这个名字就是标识符。标识符可以由编程者自由指定,但是需
10、要遵循一定的语法规定。Java对于标识符的定义有如下的规定:(1)标识符可以由字母、数字和两个特殊字符下划线(-)、美元符号($)组合而成。(2)标识符必须以字母、下划线或美元符号开头。(3)Java是大小写敏感的语言,class和Class,System和system分别代表不同的标识符,在定义和使用时要特别注意这一点。(4)应该使标识符能一定程度上反映它所表示的变量、常量、对象或类的意义。表3.2列出了一些合法、不合法的标识符,读者可以自己分析一下不合法的标识符错在何处。表3.2 合法与不合法的标识符的例子 合法标识符不合法标识符FirstJavaApplet1FirstJavaAppli
11、cationMySalary12Tree&Glasses-isTrue-isTrue-$theLastOneJava BuilderHelloWorld273.153.2.3 常量常量一经建立,在程序运行的整个过程中都不会改变。Java中常用的常量有布尔常量、整型常量、字符常量、字符串常量和浮点常量。1.布尔常量布尔常量包括true和false,分别代表真和假。2.整型常量整型常量可以用来给整型变量赋值,整型常量可以采用十进制、八进制和十六进制表示。十进制的整型常量用非0开头的数值表示,如100,-50;八进制的整型常量用以0开头的数字表示,如017代表十进制的数字15;十六进制的整型常量用0
12、 x开头的数值表示,如0 x2F代表十进制的数字47。整型常量按照所占用的内存长度,又可分为一般整型常量和长整型常量,其中一般整型常量占用32位,长整型常量占用64位。长整型常量的尾部有一个大写的L或小写的l,如-386L,017777l。3.浮点常量浮点常量表示的是可以含有小数部分的数值常量。根据占用内存长度的不同,可以分为一般浮点常量和双精度浮点常量两种。一般浮点常量占用32位内存,用F、f表示,如19.4F,3.0513E3,8701.52f;双精度浮点常量占用64位内存,用带D或d或不加后缀的数值表示,如2.433E-5D,700041.273d,3.1415。与其他高级语言类似,浮点
13、常量还有一般表示法和指数表示法两种不同的表示方法。4.字符常量字符常量用一对单引号括起的单个字符表示,这个字符可以直接是Latin字母表中的字符,如a,Z,8,#;也可以是转义符,还可以是要表示的字符所对应的八进制数或Unicode码。转义符是一些有特殊含义、很难用一般方式表达的字符,如回车、换行等。为了表达清楚这些特殊字符,Java中引入了一些特别的定义。所有的转义符都用反斜线()开头,后面跟着一个字符来表示某个特定的转义符,详见表3.3。表3.3 转义符 引用方法对应Unicode码意义bu0008退格tu0009水平制表符tabnu000a换行fu000c表格符ru000d回车u0022
14、双引号u0027单引号u005c反斜线表3.3中间一列表示的是一个字符的Unicode码,还可以用八进制表示一个字符常量。如101就是用八进制表示一个字符常量,它与u0047和A表示的是同一个字符,作为常量它们是相同的。需要补充说明的是,八进制表示法只能表示000377范围内的字符,即不能表示全部的Unicode字符,而只能表示其中ASCII字符集的部分。5.字符串常量字符串常量是用双引号括起的一串若干个字符(可以是0个)。字符串中可以包括转义符,标志字符串开始和结束的双引号必须在源代码的同一行上。下面是几个字符串常量的例子:Hello,MynJava,How are you?1234,。在J
15、ava中可以使用连接操作符(+)把两个或更多的字符串常量串接在一起,组成一个更长的字符串。例如,How do you do?+n的结果是How do you do?n。3.2.4 变量变量是在程序的运行过程中数值可变的数据,通常用来记录运算中间结果或保存数据。Java中的变量必须先声明后使用,声明变量包括指明变量的数据类型和变量的名称,必要时还可以指定变量的初始数值。如下面的语句:boolean m-bFlag=true;声明了一个布尔类型的简单变量,名字为m-bFlag,该变量的初值是逻辑真。由于声明变量的语句也是Java程序中的一个完整的语句,所以它与其他Java语句一样需要用分号结束。下
16、面是其他几个变量声明的例子:char myCharacter=B;long MyLong=-375;int m-iCount=65536;double m-dScroe;声明变量又称为创建变量,执行变量声明语句时系统根据变量的数据类型在内存中开辟相应的空间并登记变量名称、初始值等信息。Java的变量有一定的生存期和有效范围,与C语言一样,Java用大括号将若干语句组成语句块,变量的有效范围就是声明它的语句所在的语句块,一旦程序的执行离开了这个语句块,变量就没有意义,不能再使用了。例 3-1 UseVariable.java1:public class UseVariable2:3:public
17、 static void main(String args)4:5:boolean b=true;6:short si=128;7:int i=-99;8:long l=123456789L;9:char ch=J;10:float f=3.1415925F;11:double d=-1.04E-5;12:String s=你好!;13:System.out.println(布尔型变量 b=+b);14:System.out.println(短整型变量 si=+si);15:System.out.println(整型变量 i=+i);16:System.out.println(长整型变量 l=
18、+l);17:System.out.println(字符型变量 ch=+ch);18:System.out.println(浮点型变量 f=+f);19:System.out.println(双精度型变量d=+d);20:System.out.println(字符型对象 s=+s);21:22:图3.1是例3-1的运行结果。图 3.1 例3-1的运行结果 例3-1是一个字符界面的Java Application程序,其中定义了若干个变量并用相应类型的常量为它们赋初始值。其中第10句中特别使用了浮点常量3.1415925F(有兴趣的读者可以去掉常量后面的字符F,再尝试编译看能得到什么结果)。第1
19、1句中的双精度常量使用科学计数法表示。第12句定义了一个字符串对象,String不是基本数据类型,而是一个系统定义的类名,每一个字符串变量实际上都是一个字符串对象。但是由于字符串是十分常用的对象,它的声明和创建可以简化成第12句那样的形式。第13句到第20句使用System.out.println()这个系统已经定义好的方法来输出前面所定义的所有变量的数值。每个语句首先利用一个字符串常量作为解释性信息,然后把各种数据类型的数据转化成字符串的形式,用“+”拼接在前面的字符串常量的后面,共同输出。输出完毕后这个方法将把光标换到下一行,准备下一次输出。例 3-2 getNumber.java 1:i
20、mport java.io.*;2:3:public class getNumber4:5:public static void main(String args)6:7:int i=0;8:String s;9:10:try11:System.out.print(请输入一个整型数:);12:BufferedReader br=13:new BufferedReader(new InputStreamReader(System.in);14:s=br.readLine();15:i=Integer.parseInt(s);16:catch(IOException e)17:System.out
21、.print(你输入了数字:+i);18:System.out.println(t,对吗?);19:20:图3.2是例3-2的运行结果。图 3.2 例3-2的运行结果 例3-2接受用户从键盘输入的一个字符串,然后把它转化成整型数据并输出。如在图3.2中用户输入了字符串“245”,利用例3-2第15句中系统定义的方法Integer.parseInt()就可以把它转化成数字245。其中Integer是系统定义的一个类,对应基本数据类型int,parseInt()是Integer类的一个方法,可以把数字字符组成的字符串转化成真正的整型数字。另外,第11句和第17句还使用了一个新的输出方法System
22、.out.print()。这个方法的用法和作用与System.out.println()基本相同,唯一的区别是输出了数据后并不回车。第18句使用转义符t将输出数据与字符串常量拉开距离。例 3-3 getDouble.java1:import java.applet.*;2:import java.awt.*;3:import java.awt.event.*;4:5:public class getDouble extends Applet implements ActionListener6:7:Label prompt;8:TextField input;9:double d=0.0;10
23、:11:public void init()12:13:prompt=new Label(请输入一个浮点数:);14:input=new TextField(10);15:add(prompt);16:add(input);17:input.addActionListener(this);18:19:public void paint(Graphics g)20:21:g.drawString(你输入了数据:+d,10,50);22:23:public void actionPerformed(ActionEvent e)24:25:d=Double.valueOf(input.getText
24、().doubleValue();26:repaint();27:28:图3.3是例3-3的运行结果。图 3.3 例3-3的运行结果 例3-3是一个图形界面下的Java Applet程序,通过这个例子可以了解如何在图形界面下输入数值数据。用户在文本框对象input中输入字符串并回车后,程序接受用户输入的这个字符串(在图3.3中是“3.1415926”),利用第25句中的方法Double.valueOf().doubleValue()将这个字符串转化成真正的浮点数据赋值给双精度变量d(在图3.3中是3.1415926)。第26句调用Applet类中系统定义好的方法repaint(),这个方法将调
25、用第19句到22句的方法paint(),把变量d中的数据显示出来。为体会图形界面输入数据的方法,读者可以针对例3-3做如下实验:(1)删除第15句,编译并运行,观察界面的变化。(2)恢复第15句,删除第16句,编译并运行,观察界面的变化。(3)恢复第16句,删除第17句,编译并运行,观察界面的变化。(4)恢复第17句,删除第26句,编译并运行,观察界面的变化。3.3 表达式表达式是由变量、常量、对象、方法调用和操作符组成的式子。符合语法规则的表达式可以被编译系统理解、执行或计算,表达式的值就是对它运算后所得的结果。组成表达式的Java操作符有很多种,代表了多种的丰富的操作运算,包括赋值运算、算
26、术运算、关系运算和逻辑运算等。3.3.1 赋值与强制类型转换 赋值运算符对应了赋值运算,即赋予程序里的变量或对象一定的内容。简单的赋值运算是把一个表达式的值直接赋给一个变量或对象,使用的赋值运算符是“=”,其格式如下:变量或对象=表达式;其中赋值号右边的表达式可以是常量、另一个变量或对象以及方法的返回值。下面是一些简单赋值运算的例子:i=0;j=i;k=i+j*5;MyFirstString=MyDouble.toString();MySecondString=MyFirstString;需要注意的是,当赋值号的左边是一个对象名时,赋值运算符将把右边表达式所得的对象的引用赋值给它,而不是为这个
27、对象开辟新的内存空间并把右边对象的所有内容赋值给它。在使用赋值运算时,可能会遇到等号左边的数据类型和等号右边的数据类型不一致的情况,这时需要把等号右边的数据类型转化成等号左边的数据类型。某些情况下,系统可以自动完成这种类型转换,另一些情况下就要用到强制类型转换。Java的类型转换有较严格的规定:凡是将变量从占用内存较少的短数据类型转化成占用内存较多的长数据类型时,可以不做显式的类型转换声明;而将变量从较长的数据类型转换成较短的数据类型时,则必须做强制类型转换。例如下面的例子中分别定义了16位的字节类型变量MyByte和32位的整数类型变量MyInteger:byte MyByte=10;int
28、 MyInteger=-1;如果把MyByte的值赋给MyInteger,则可以直接写成:MyInteger=MyByte;而把MyInteger的值赋给MyByte,则必须写成MyByte=(byte)MyInteger;先把变量MyInteger中保存的数值的数据类型从int变成byte后才能赋给MyByte,其中,(byte)就是在做强制类型转换。其一般格式是:(数据类型)变量名或表达式3.3.2 算术运算算术运算是针对数值类型操作数进行的运算,算术运算符根据需要的操作数个数的不同,可以分为双目运算符和单目运算符两种。1.双目运算符 表3.4 双目算术运算符 运算符运算例功能+加a+b求
29、a与b相加的和-减a-b求a与b相减的差*乘a*b求a与b相乘的积/除a/b求a除以b的商%取余a%b求a除以b所得的余数这里有两个需要注意的问题:(1)只有整数类型(int,long,short)的数据才能够进行取余运算,float和double不能取余。(2)两个整数类型的数据做除法时,结果是截取商数的整数部分,而小数部分被截断。如果希望保留小数部分,则应该对除法运算的操作数做强制类型转换。例如1/2的结果是0,而(float)1)/2的结果是0.5。2.单目运算符单目运算符的操作数只有一个,算术运算中有三个单目运算符。表3.5 单目算术运算符 运算符运算例功能等价+自增a+或+aa=a+
30、1-自减a-或-aa=a-1-求相反数-aa=-a单目运算符中的自增和自减,其运算符的位置可以在操作数的前面,也可以在操作数的后面;当进行单目运算的表达式位于一个更复杂的表达式内部时,单目运算符的位置将决定单目运算与复杂表达式二者执行的先后顺序。如下面的例子里,单目运算符在操作数变量的前面,则先执行单目运算,修改变量的值后用这个新值参与复杂表达式的运算。int x=2;int y=(+x)*3;运算执行的结果是 x=3,y=9。而在下面的例子里,由于单目运算符放在操作数变量的后面,则先计算复杂表达式的值,最后再修改变量的取值。int x=2;int y=(x+)*3;运算执行的结果是x=3,y
31、=6。可见,单目运算符的位置不同,虽然对操作数变量没有影响,但却会改变整个表达式的值。例 3-4 TestArithmetic.java 1:import java.applet.*;2:import java.awt.*;3:import java.awt.event.*;4:5:public class UseArithmetic extends Applet implements ActionListener6:7:Label prompt;8:TextField input1,input2;9:Button btn;10:int a=0,b=1;11:12:public void in
32、it()13:14:prompt=new Label(请输入两个整型数据:);15:input1=new TextField(5);16:input2=new TextField(5);17:btn=new Button(计算);18:add(prompt);19:add(input1);20:add(input2);21:add(btn);22:btn.addActionListener(this);23:24:public void paint(Graphics g)25:26:g.drawString(a+b+=+(a+b),10,50);27:g.drawString(a+-+b+=+
33、(a-b),10,70);28:g.drawString(a+*+b+=+(a*b),10,90);29:g.drawString(a+/+b+=+(a/b),10,110);30:g.drawString(a+%+b+=+(a%b),10,130);31:32:public void actionPerformed(ActionEvent e)33:34:a=Integer.parseInt(input1.getText();35:b=Integer.parseInt(input2.getText();36:repaint();37:38:例3-4是图形界面中的Java Applet程序,它
34、利用两个文本框对象input1和input2接受用户输入的两个数据。当用户单击按钮“计算”时,程序将把这两个字符串转化为整型数据赋值给同类的两个变量a和b,然后通过repaint()方法调用第24行到第31行的paint()方法,以a和b为操作数,计算它们四则运算的结果并输出。图3.4是例3-4运行结果。图 3.4 例3-4的运行结果 3.3.3 关系运算关系运算是比较两个数据之间的大小关系的运算,常用的关系运算列于表3.6中:表 3.6 关系运算符运算符运算=等于!=不等于大于=大于等于 +b+=+(ab),10,50);27:g.drawString(a+b+=+(a=+b+=+(a=b)
35、,10,90);29:g.drawString(a+=+b+=+(a y&x+=y-;在计算布尔型的变量b的取值时,先计算&左边的关系表达式x y,得结果为假,根据逻辑与运算的规则,只有参加与运算的两个表达式都为真时,最后的结果才为真;所以不论&右边的表达式结果如何,整个式子的值都为假,右边的表达式就不予计算执行了;最后三个变量的取值分别是:x为3,y为5,b为false。如果把上题中的简洁与(&)换为非简洁与(&),则与号两边的两个表达式都会被运算,最后三个变量的取值分别是:x为4,y为4,b为false。同理,对于简洁或(|),若左边的表达式的运算结果为真,则整个或运算的结果一定为真,右边
36、的表达式就不会再运算执行了。例 3-6 UseLogical.java 10:boolean a=true,b=false;24:public void paint(Graphics g)25:26:g.drawString(a+&+b+=+(a&b),10,50);27:g.drawString(a+&+b+=+(a&b),10,70);28:g.drawString(a+|+b+=+(a|b),10,90);29:g.drawString(a+|+b+=+(a|b),10,110);30:g.drawString(a+b+=+(ab),10,130);31:g.drawString(!+b
37、+=+(!b),10,150);32:33:public void actionPerformed(ActionEvent e)34:35:a=Boolean.valueOf(input1.getText().booleanValue();36:b=Boolean.valueOf(input2.getText().booleanValue();37:repaint();38:图3.6是例3-6的运行结果。例3-6在例3-4的基础上修改了第10句,使a,b两个变量可以接受布尔型数据;修改了第33到第3 8 句 的 事 件 处 理 方 法,利 用 系 统 定 义 的 方 法Boolean.valu
38、eOf().booleanValue()将用户输入的字符串转化成布尔型数据;修改了第24行到第32行的paint()方法,使之显示两个布尔型量逻辑运算的结果。图 3.6 例3-6的运行结果 3.3.5 位运算运算是对操作数以二进制比特位为单位进行的操作和运算,位运算的操作数和结果都是整型量。几种位运算符和相应的运算规则列于表3.8中。表 3.8 位运算符运算符运算例运算规则位反 x将x按比特位取反右移x ax各比特位右移a位左移x 不带符号的右移x ax各比特位右移a位 左边的空位一律填零移位运算是将某一变量所包含的各比特位按指定的方向移动指定的位数,表3.9是三个移位运算符的例子。表 3.9
39、 移位运算 X(十进制表示)二进制补码表示x 2x 23000011110011110000000011100000111-17111011111011110011111011001110113.3.6 其他运算符 1.三目条件运算符?:Java中的三目条件运算符与C语言完全相同,使用形式是:x?y:z其规则是,先计算表达式x的值,若x为真,则整个三目运算的结果为表达式y的值;若x为假,则整个运算结果为表达式z的值。参看下面的例子:int x=5,y=8,z=2;int k=x 3?y:z;/x 0?x:-x;/y为x的绝对值 2.复杂赋值运算符复杂赋值运算符是在先进行某种运算之后,再把运算的
40、结果做赋值。表3.10列出了所有的复杂赋值运算。表 3.10 复杂赋值运算符运算符例子等价于+=x+=ax=x+a-=x-=ax=x-a*=x*=ax=x*a/=x/=ax=x/a%=x%=ax=x%a&=x&=ax=x&a|=x|=ax=x|a=x=ax=x a=x=ax=x=x=ax=x a3.括号与方括号括号运算符()在某些情况下起到改变表达式运算先后顺序的作用;在另一些情况下代表方法或函数的调用。它的优先级在所有的运算符中是最高的。方括号运算符 是数组运算符,它的优先级也很高,其具体使用方法将在后面介绍。4.对象运算符对象运算符instanceof用来测定一个对象是否属于某一个指定类或
41、其子类的实例,如果是则返回true,否则返回false。例如:boolean b=MyObject instanceof TextField;3.3.7 运算符的优先级与结合性 运算符的优先级决定了表达式中不同运算执行的先后顺序。如关系运算符的优先级高于逻辑运算符,x y&!z相当于(x y)&(!z)。运算符的结合性决定了并列的相同运算的先后执行顺序。如对于左结合的“+”,x+y+z等价于(x+y)+z,对于右结合的“!”,!x等价于!(!x)。表3.11列出了Java主要运算符的优先级和结合性。表 3.11 Java运算符的优先级与结合性优先级描述运算符结合性1最高优先级.()左/右2单目
42、运算-!+-强制类型转换符右3算术乘除运算*/%左4算术加减运算+-左5移位运算 左6大小关系运算 =左7相等关系运算=!=左8按位与,非简洁与&左9按位异或运算左10按位或,非简洁或|左11简洁与&左12简洁或|左13三目条件运算?:右14简单、复杂赋值=运算符=右3.3.8 注释 注释是程序不可少的部分。Java的注释符有两种。一种是行注释符“/”,以“/”开头到本行末的所有字符被系统理解为注释,不予编译。如:/This a test program of what is to be done另一种注释符是块注释符“/*”和“*/”,其中“/*”标志着注释块的开始,“*/”标志着注释块的结
43、束。“/*”和“*/”可以括起若干个注释行。如:/*程序名:项目名:编写时间:功能:输入/输出:*/3.4 流程控制语句 流程控制语句是用来控制程序中各语句执行顺序的语句,是程序中非常关键和基本的部分。流程控制语句可以把单个的语句组合成有意义的,能完成一定功能的小逻辑模块,能否熟练地运用流程控制语句往往很大程度上影响所编写程序的质量。最主要的流程控制方式是结构化程序设计中规定的三种基本流程结构。3.4.1 结构化程序设计的三种基本流程 结构化程序设计原则是公认的面向过程编程应遵循的原则,它使得程序段的逻辑结构清晰、层次分明,有效地改善了局部程序段的可读性和可靠性,保证了其质量,提高了开发效率。
44、结构化程序设计的最基本的原则是:任何程序都可以且只能由三种基本流程结构构成,即顺序结构、分支结构和循环结构。这三种结构的构成参见图3.7。图 3.7 结构化程序设计的三种基本结构顺序结构是三种结构中最简单的一种,即语句按照书写的顺序依次执行;分支结构又称为选择结构,它将根据计算所得的表达式的值来判断应选择执行哪一个流程的分支;循环结构则是在一定条件下反复执行一段语句的流程结构。这三种结构构成了程序局部模块的基本框架。Java语言虽然是面向对象的语言,但是在局部的语句块内部,仍然需要借助于结构化程序设计的基本流程结构来组织语句,完成相应的逻辑功能。Java的语句块是由一对大括号括起的若干语句的集
45、合。Java中,有专门负责实现分支结构的条件分支语句和负责实现循环结构的循环语句。3.4.2 分支语句 Java中的分支语句有两个,一个是负责实现双分支的if语句,另一个是负责实现多分支的开关语句switch。1.if语句if语句的一般形式是:if(条件表达式)语句块;/if分支else 语句块;/else分支 其中条件表达式用来选择判断程序的流程走向,在程序的实际执行过程中,如果条件表达式的取值为真,则执行if分支的语句块,否则执行else分支的语句块。在编写程序时,也可以不书写else分支,此时若条件表达式的取值为假,则绕过if分支直接执行if语句后面的其他语句。语法格式如下:if(条件表
46、达式)语句块;/if分支其他语句;下面是一个if语句的简单例子,是实现求某数的绝对值功能的程序片段。if(x b)32:if(ac)33:max=a;34:else35:max=c;36:else37:if(bc)38:max=b;39:else 40:max=c;41:result.setText(三数中最大值是:+max);42:43:例3-7中的程序接受用户输入的三个整数,在用户单击“比较”按钮后程序调用方法actionPerformed()比较并输出其中的最大值。第31句到第40句使用if语句的嵌套比较并得到三数中的最大值。第41句中使用了Label类对象result的一个系统定义好的
47、方法setText()把原来显示的提示信息变换成输出信息。图3.8是例3-7程序运行的结果。图 3.8 例3-7的运行结果2.switch语句switch语句是多分支的开关语句,它的一般格式如下:switch(表达式)case 判断值1:语句块1 /分支1 case 判断值2:语句块2 /分支2 case 判断值n:语句块n /分支n default:语句块n+1 /分支n+1 switch语句在执行时,首先计算表达式的值,这个值必须是整型或字符型,同时应与各个case分支的判断值的类型相一致。计算出表达式的值之后,将它先与第一个case分支的判断值相比较,若相同,则程序的流程转入第一个cas
48、e分支的语句块;否则,再将表达式的值与第二个case分支相比较依此类推。如果表达式的值与任何一个case分支都不相同,则转而执行最后的default分支;在default分支不存在的情况下,则跳出整个switch语句。需要注意的是,switch语句的每一个case判断,都只负责指明流程分支的入口点,而不负责指定分支的出口点,分支的出口点需要编程人员用相应的跳转语句来标明。看下面的例子:switch(MyGrade)case A:MyScore=5;case B:MyScore=4;case C:MyScore=3;default :MyScore=0;假设变量MyGrade的值为“A”,执行完
49、switch语句后,变量MyScore的值被赋成0,而不是5!因为case判断只负责指明分支的入口点,表达式的值与第一个case分支的判断值相匹配后,程序的流程进入第一个分支,将MyScore的值置为5。由于没有专门的分支出口,所以流程将继续沿着下面的分支逐个执行,MyScore的值被依次置为4,3,最后变成0。如果希望程序的逻辑结构正常完成分支的选择,则需要为每一个分支另外编写退出语句。修改后的例子如下:switch(MyGrade)case A:MyScore=5;break;case B:MyScore=4;break;case C:MyScore=3;break;default :My
50、Score=0;break是流程跳转语句。通过引入break语句,定义了各分支的出口,多分支开关语句的结构就完整了。在某些情况下,switch语句的这个只有分支入口、没有出口的功能也有它独特的适用场合。如在若干判断值共享同一个分支时,就可以实现由不同的判断语句流入相同的分支。下面的例子是该例的进一步修改,仅划分及格与不及格。switch(MyGrade)case A:case B:case C:MyScore=1;/及格 break;default:MyScore=0;/不及格 3.4.3 循环语句 循环结构是在一定条件下,反复执行某段程序的流程结构,被反复执行的程序被称为循环体。循环结构是程