第5章创建类的成员属性和方法 主要知识点 Java语言的基本组成; 运算符与表达式; 程序控制结构; Java程序的编程规范; 类成员方法的创建方法。 学习目标 能根据Java语言的基本语法和程序结构声明类的成员方法,从而定义完整的类。 在第4章中学习了类的定义方法,能够对类的属性进行声明。一个完整的类是由若干属性和方法构成。本章将在学习Java语法的基础上,学会定义类的成员方法,从而能够编写简单的应用程序,通过“仿QQ聊天软件”项目的分析,掌握类的定义与用法。 5.1Java语言的基本组成 Java语言主要由5种元素组成: 标识符、关键字、文字、运算符和分隔符。各元素有着不同的语法含义和组成规则,它们互相配合,共同完成Java语言的语意表达。 5.1.1分隔符 分隔符用于将一条语句分成若干部分,便于系统识别,让编译程序确认代码在何处分隔。Java语言的分隔符有三种: 空白符、注释语句、普通分隔符。 1. 空白符 在Java程序中,换行符和回车键均表示一行的结束,都是典型的空白符,空格键和Tab制表健也是空白符。为了增加程序可读性,Java语句的成分之间可以插入任何多个空白符,在编译时,系统自动忽略多余的空白符。 2. 注释语句 注释语句是为了提高程序的可读性而附加的内容,编译程序对注释部分既不显示也不执行,有没有注释部分不会影响程序的执行。Java提供了三种形式的注释: (1) // 一行的注释内容 以//开始,最后以按回车键结束,表示从//到本行结束的所有字符均为注释内容。 (2) /*一行或多行的注释内容*/ 从/*到*/ 间的所有字符(可能包括几行内容)都作为注释内容。 以上两种注释可用于程序的任何位置。 (3) /**文档注释内容*/ 当这类注释出现在任何声明之前时将会作特殊处理,它们不能再用在代码的任何地方。表示被括起来的正文部分,应该作为声明项目的描述,而被包含在自动产生的文档中。 编写程序时,除了加入适当的空白符和注释内容外,还要尽可能使用层次缩进格式,使同一层语句的起始列号位置相同,层次分明,便于阅读和维护,形成良好的编程习惯。 3. 普通分隔符 普通分隔符用于区分程序中的各种基本成分,但它在程序中有确切的意义,不可忽略。包括4种:  花括号({ }),用来定义复合语句、类体、方法体以及进行数组的初始化。  分号(;),表示一条语句的结束。  逗号(,),用来分隔变量说明和方法的参数。  冒号(:),说明语句标号。 例51分隔符的用法。 /** 程序名:MyClass.java 功能:简单程序使用举例 开发日期:2022年3月10日 */ public class MyClass{ //这里定义一个类 public static void main(String args[]){ //定义程序的主方法 int int1,int2;//声明2个整型变量 /* 从这里开始书写方法的内容 */ … } //main()方法结束 } //MyClass类结束 程序说明: 对于应用程序,必须有一个主方法main(),是程序执行的入口,其中的参数格式是String args[],表示含有String字符串类型的数组参数args,args是数组名,是用户自定义标识符,可以改成其他名称。以上参数也可以写成String[] args的形式。main()方法的返回值是void,表示无返回值,是公有的(public),是类的静态成员(static)。 5.1.2关键字 关键字用来表示特定的意义,也叫保留字,由系统本身使用,不能用作标识符。Java的关键字共有48个,所有的关键字都是小写字母,如表51所示。 表51Java关键字 abstractbooleanbreakbytecase catchcharclasscontinuedefault dodoubleelseextendsfalse finalfinallyfloatforif implementsimportinstanceofintinterface longnativenewnullpackage privateprotectedpublicreturnshort staticsuperswitchsynchronizedthis throwthrowstransienttruetry voidvolatilewhile 5.2运算符与表达式 运算符指明对操作数所进行的运算。按操作数的数目来分,可以有单目运算符(如++、--),双目运算符(如+、>)和三目运算符(如?:),它们分别对应于一个、两个和三个操作数。对于单目运算符来说,可以有前缀表达式(如++i )和后缀表达式(如i++),对于双目运算符来说则采用中缀表达式(如a+b)。按照运算符功能来分,基本的运算符有下面几类:  算术运算符(+,-,*,/,%,++,--)  关系运算符(>,<,>=,<=,==,!=)  布尔逻辑运算符(!,&&,||)  位运算符(>>,<<,>>>,&,|,^,~)  赋值运算符(=,及其扩展赋值运算符如+=)  条件运算符( ?:)  其他,包括分量运算符(.)、下标运算符[]、实例运算符instanceof、内存分配运算符new、强制类型转换运算符(类型)、方法调用运算符()等。 5.2.1算术运算符 算术运算符作用于整型或浮点型数据,完成算术运算。 1. 双目算术运算符 双目算术运算符包括+、-、*、/、%(取模)5种运算符。 Java对加运算符进行了扩展,使它能够进行字符串的连接,如"abc"+"de",得到串"abcde"。取模运算符%的操作数可以是浮点数,如37.2%10=7.2。 2. 单目算术运算符 单目算术运算符如表52所示(op表示操作数)。 表52单目运算符 运算符用法描述 ++ op正值 -- op负值 ++++ op,op ++加1 ---- op,op --减1 i++与++i的区别: i++在使用i之后,使i的值加1,因此执行完i++后,整个表达式的结果仍为i,而i的值变为了i+1。++i在使用i之前,使i的值加1,因此执行完++i后,整个表达式和i的值均为i+1。例如,初值a=1,b=1,执行a=b++后a=1,b=2,而执行a=++b后,a=2,b=2。 5.2.2关系运算符 关系运算符用来比较两个值的大小关系,返回布尔类型的值true或false。关系运算符都是双目运算符,包括>、>=、<、<=、==、!=、<>共7个。 在Java中,任何数据类型的数据(包括基本类型和组合类型)都可以通过==或!=来比较是否相等,结果返回true或false。关系运算符常与布尔逻辑运算符一起使用,作为流控制语句的判断条件。 5.2.3逻辑运算符 逻辑运算符包括&&(逻辑与)、||(逻辑或)、! (逻辑非),逻辑表达式的结果是一个布尔值true或false。 对于布尔逻辑运算,先求出运算符左边的表达式的值,对于或运算,如果为true,则整个表达式的结果为true,不必再对运算符右边的表达式再进行运算; 同样,对于与运算,如果左边表达式的值为false,则不必再对右边的表达式求值,整个表达式的结果为false,这种逻辑运算又称为逻辑短路与和逻辑短路或。 例52逻辑运算符的应用。 public class Test502{ public static void main(String args[]){ int a=25,b=3; boolean d=a=60"); break; case 'D' : System.out.println(grade+" is <60"); break; default : System.out.println("input error"); } } } 从该例可以看到break语句的作用,如果子句中缺少了break语句,输出结果会出错。 3. break语句 在switch语中,break语句用来终止switch语句的执行,使程序从switch语句后的第一个语句开始执行。可以为每个代码块加一个括号,一个代码块通常是用大括号({ })括起来的一段代码。加标号的格式如下: BlockLabel: { codeBlock } break语句的第二种使用情况就是跳出它所指定的块,并从紧跟该块的第一条语句处执行。其格式为: break BlockLabel; 即用break来实现程序流程的跳转,不过应该尽量避免使用这种方式。 4. 返回语句return return语句从当前方法中退出,返回到调用该方法的语句处,并从紧跟该语句的下一条语句继续程序的执行。返回语句有两种格式: 格式1: return expression; 用于返回一个值给调用该方法的语句,返回值的数据类型必须和方法声明中的返回值类型一致。可以使用强制类型转换来使类型一致。 格式2: return; 当方法说明中用 void声明返回类型为空时,应使用这种格式,它不返回任何值。return 语句通常用在一个方法体的最后,以退出该方法并返回一个值。Java中,单独的return语句用在一个方法体的中间时,会产生编译错误,因为这时会有一些语句执行不到。但可以通过把return语句嵌入某些语句(如ifelse)来使程序在未执行完方法中的所有语句时退出,例如: int method(int num) { return num; //本句会产生编译错误 if (num>0) return num; …// 本句能否执行,取决于num的值 } 5.3.2循环语句 循环语句的作用是反复执行一段代码,直到满足终止循环的条件为止,一个循环一般应包括四部分内容。  初始化部分(initialization): 设置循环的一些初始条件,如计数器清零等。  循环体部分(body): 反复循环的一段代码,可以是单一的一条语句,也可以是复合语句。  迭代部分(iteration): 这是在当前循环结束,下一次循环开始前执行的语句,常常用来使计数器变量加1或减1。  终止部分(termination): 通常是一个布尔表达式,每一次循环都要对该表达式求值,以验证是否满足循环终止条件。 Java提供的循环语句有while、dowhile和for三种语句,下面分别介绍。 1. while语句 while语句实现“当型”循环,一般格式为: [initialization]//初始化 while (termination){//循环条件 body; //循环体 [iteration;]//迭代,改变循环变量的值 } 布尔表达式(termination)表示循环条件,值为true时,循环执行大括号中的语句。while语句首先判断循环条件,当条件成立时,才执行循环体中的语句,如果一开始条件就不成立,可能循环体一次都不会执行,这是“当型”循环的特点。 2. dowhile语句 dowhile语句实现“直到型”循环,一般格式为: [initialization] do { body; [iteration;] } while (termination); // dowhile语句首先执行循环体,然后判断循环条件,若结果为true,则循环执行大括号中的语句,直到布尔表达式的结果为false。与while语句不同的是,dowhile语句的循环体至少执行一次,这是“直到型”循环的特点。 3. for语句 for语句实现固定次数的循环,一般格式为: for (initialization; termination; iteration){ body; }  for语句执行时,首先执行初始化操作,然后判断循环条件是否满足,如果满足,则执行循环体中的语句,最后执行迭代部分。完成一次循环后,重新判断终止条件。  可以在for语句的初始化部分声明一个变量,它的作用域为整个for 语句。  for语句通常用来执行循环次数确定的情况(如对数组元素进行操作),也可以根据循环结束条件执行循环次数不确定的情况。  在初始化部分和迭代部分可以使用逗号语句来进行多个操作。逗号语句是用逗号分隔的语句序列。例如: for(i=0,j=10; i0){ //循环条件 sum+=n; //循环体 n--; //迭代 } System.out.println("sum is "+sum); System.out.println("\n**** do_while statement ****"); n=0; //初始化 sum=0; do{ sum+=n; //循环体 n++; //迭代 }while(n<=10); //循环条件 System.out.println("sum is "+sum); System.out.println("\n**** for statement ****"); sum=0; for(int i=1; i<=10; i++){ //初始化,循环条件,迭代 sum+=i; //循环体 } System.out.println("sum is "+sum); } } 运行结果为: **** while statement **** sum is 55 **** do_while statement **** sum is 55  **** for statement **** sum is 55 可以从中来比较这三种循环语句,从而在不同的场合选择合适的语句。 5.3.3Java编程规范 养成良好的编程风格是程序员应具备的基本素质,运用Java编程也要遵守Java编程规范,这对于读懂别人的程序和让别人理解自己的程序都十分重要。 1. 一般原则  尽量使用完整的英文单词描述符。  采用适用于相关领域的术语。  采用大小写混用,可读性更好。  避免使用相似或相同的名字,或者仅仅是大小写不同的名字。  少用下画线(除静态常量等)。 2. 具体要求  包(Package): 包名采用完整的英文描述符,都由小写字母组成。  类(Class): 类名采用完整的英文描述符,所有单词的第一个字母均大写,如CustomerName,SavingsAccountBank。  接口(Interface): 接口名采用完整的英文描述符说明接口封装,所有单词的第一个字母大写。习惯上,接口名字后面加上后缀 able、ible 或者er,但这不是必需的。如 Contactable、Prompter。  组件(Component): 使用完整的英文描述来说明组件的用途,末端应接上组件类型,如okButton、customerList、fileMenu。  异常(Exception): 通常采用字母 e 表示异常的实例,这是个特例,表示单词Exception的第一个字母,易于记忆。  变量、属性、方法: 采用完整的英文描述,第一个单词首字母小写,后面所有单词的首字母大写。 如firstName、lastName。  获取成员函数: 被访问字段名的前面加上前缀 get,如getFirstName()、getLastName()。  布尔型获取成员函数: 所有的布尔型获取函数必须用单词 is 做前缀,表示“是不是……”这样一个意义,如isPersistent()、isString()。  设置成员函数: 被访问字段名的前面加上前缀set表示设置,如setFirstName()、setLastName()、setWarpSpeed()。  普通成员函数: 采用完整的英文描述说明成员函数功能,第一个单词尽可能采用动词,第一个字母小写,类似于变量名,如openFile()、addAccount()。  静态常量(static final): 全部采用大写字母,单词之间用下画线分隔,如PI、MIN_BALANCE、DEFAULT_DATE。  循环变量: 用于循环语句中控制循环次数,通常用i、j、k 或者 counter表示。 5.4数组 数组是有序数据的集合,数组中的每个元素具有相同的类型,数组名用下标来区分数组中的元素位置,数组可分为一维数组和多维数组。 5.4.1一维数组 1. 一维数组的定义 一维数组的定义格式为: type arrayName[]; 或者 type [] arrayName; 其中类型type可以为Java中任意的数据类型,包括简单类型和复合类型(也可以是数组),数组名 arrayName为一个合法的标识符,[]指明该变量是一个数组类型变量。例如: int intArray[]; int [] intArray; 声明了一个整型数组,数组中的每个元素为整型数据。Java在数组的定义中并不为数组元素分配内存,因此[]中不能指出数组中元素个数(数组长度),不允许访问这个数组的任何元素。必须为它分配存储空间后才能访问它的元素,这时要用到new命令,其格式是: arrayName=new type[arraySize]; arraySize指明数组的长度。如: “intArray=new int[10];”为一个整型数组分配10个int型整数所占据的内存空间,其下标分量为0~9。 通常,这两部分可以合在一起,用一条语句完成,格式是: type arrayName=new type[arraySize]; 例如: int intArray=new int[3]; 2. 一维数组元素的引用 定义了一个数组,并用运算符new为它分配了内存空间后,就可以引用数组中的每一个元素了。数组元素的引用方式为: arrayName[index] 其中,index为数组下标,它可以为整型常数或表达式。如a[8]、b[i](i为整型)、c[2*i]等。下标从0开始,一直到数组的长度减1。对于上面例子中的intArray数来说,它有10个元素,分别从intArray[0]到intArray[9],但没有intArray[10]。 Java对数组元素要进行越界检查以保证安全性。同时,每个数组都有一个属性length指明它的长度(元素个数),例如: intArray.length表示数组intArray的长度。 3. 一维数组的初始化 对数组元素可以按照上述的例子进行赋值,也可以在定义数组的同时初始化。 例如: int a[]={1,2,3,4,5}; 但“int a[5]={1,2,3,4,5};”是非法的,系统自动统计数据个数,不要用户确定。 用逗号(,)分隔数组的各个元素,系统自动为数组分配一定的存储空间。 例56从小到大冒泡法排序数组,冒泡排序是对相邻的两个元素进行比较,并把小的元素交换到前面。 public class Test506{ public static void main(String args[]){ int i,j; int intArray[]={30,1,-9,70,25}; //数组初始化 int l=intArray.length; //数组长度赋值给变量l for(i=0;iintArray[j]){ //以下3行用于交换位置 int t=intArray[i]; intArray[i]=intArray[j]; intArray[j]=t; } for(i=0;i