本文共 7103 字,大约阅读时间需要 23 分钟。
3.1 变量
根据第2章可知,对象的状态存储在字段中:2.1节已经介绍了字段的概念,但读者仍可能会问:命名字段有什么规则和约定?除了整型,是否还有其他数据类型?字段在声明时是否必须初始化?如果字段没有显式初始化,该字段是否会被赋予一个默认值?本章将会详细解答这些问题。但在此之前,先要明确一些技术差别。Java程序语言同时使用字段和变量。对于新的开发人员而言,这是造成概念混淆的主要原因,因为两者经常看似指代同一个事物。Java程序语言定义了如下变量:
实例变量(非静态字段)。就技术而言,对象将个体状态存入非静态字段,也就是不用关键字static声明的字段。非静态字段也称为实例变量,因为对每个类实例(即对象)而言,它们的值都是唯一的。比如,一辆自行车的currentSpeed字段与另一辆自行车的currentSpeed字段无关。类变量(静态字段)。类变量是用static修饰符声明的任意字段,这就告诉编译器该变量只存在一个副本,而不管它被实例化多少次。特定类型的自行车的档数字段定义时要用static来声明,因为该档数会应用于所有的实例。代码static int numGears=6;创建该静态字段。此外,也可以添加关键字final表示该档数永远都不会变。局部变量。与对象将状态存入字段类似,方法也将临时状态存入局部变量。声明局部变量的语法与声明字段类似(例如int count=0;)。局部变量在声明时没有特殊的关键字,完全取决于变量的声明位置,也就是说方法体内有效。因此,局部变量只对声明它的方法可见,类的其他部分不能访问该局部变量。参数。在Bicycle类和“Hello World!”实例程序的main方法中我们已经见到过参数的例子。main方法的声明形式是public static void main(String[] args)。其中,变量args是main方法的参数。最重要的一点是,参数总被归为变量,而不是字段。这同样适用于后续章节将要学习的其他支持参数的构造,如构造器和异常处理器。即便如此,本章后续内容讨论字段和变量时仍采用下述标准进行区分。如果讨论的是一般的字段(不包括局部变量和参数),就采用术语字段。如果讨论适用于上述四种变量,就采用术语变量。如果上下文要求进行区分,就根据情况采用特定的术语(静态字段、局部变量等)。有时也会使用术语成员(member)。类型的字段、方法和嵌入类型等都是它的成员。3.1.1 命名程序语言都有自己的命名规则和约定,Java也不例外,其变量的命名有以下规则和约定:变量名区分大小写。变量名可以是任意合法的标识符,如以字母、美元符号($)或下划线(_)开头的无限长的Unicode字母和数字序列。但是,按约定通常采用字母开头,而不是美元符号或下划线。另外,按约定美元符号从来没有使用过。尽管有些自动生成的变量名会包含美元符号,但命名变量时应该尽量避免。这些同样适用于下划线。虽然以下划线开头命名变量是合法的,但并不鼓励采用该方法。变量命名时不支持空格。确定首个字符之后,后续字符可以是字母、数字、美元符号或下划线。当然也有一些约定或常识。命名变量时最好使用完整的单词,而不是神秘的缩写。这样命名可以提高代码的可读性。大多数情况下,这样做会提高代码的自文档化(self-documenting)程度。比如,字段名cadence、speed、gear比缩写c、s、g更直观。切记,变量名不能是关键字或保留字。如果变量名只包含一个单词,就用小写字母表示。如果包含两个或两个以上单词,后续单词的首字母要大写,如gearRatio和currentGear。如果变量保存的是常量值,如static final int NUM_GEARS=6,那么变量名的每个字母都要大写,而且后续单词用下划线分隔。按约定,其他情况都不用下划线。3.1.2 基本数据类型Java是静态类型的程序语言,也就是说,所有变量在使用前必须先声明。声明的内容包括类型和名称,如:该声明告诉程序存在一个字段gear,其数据为数字类型,初始值为1。变量的数据类型决定它可以包含的值以及该变量上可以执行的运算。除了整型(int)以外,Java程序语言还支持其他7种基本数据类型。基本数据类型由语言预定义并用保留关键字命名。基本数据类型的值之间不共享状态。Java程序语言支持以下8种基本数据类型。
1)byte数据类型表示8位带符号二进制补码整数。其最小值为-128,最大值为127。当大型数组的内存存储出问题时,byte数据类型可用于存储内存。byte类型变量的范围有限,可以作为一种文档规范。因此,它也用于代替int类型以简化代码。2)short数据类型表示16位带符号二进制补码整数。其最小值为-32?768,最大值为32?767。与byte类型一样,short类型也可以用作大型数组内存存储的应急方案。3)int数据类型表示32位带符号二进制补码整数。其最小值为-231,最大值为231-1。在Java SE 8及更高版本中,可以使用int数据类型表示无符号32位整数,其最小值为0,最大值为232-1。Interger类也支持无符号32位整数。Interger类中增加了类似于compareUnsigned和divideUnsigned的静态方法以支持无符号整数的算术运算。4)long数据类型表示64位带符号二进制补码整数。其最小值为-263,最大值为263-1。在Java SE 8及更高版本中,可以使用long数据类型表示无符号64位长整型整数,其最小值为0,最大值为264-1。使用的值超出int数据类型支持的范围时可使用该数据类型。Long类也包含类似于compareUnsigned和devideUnsigned的方法以支持无符号长整型数的算术运算。5)float数据类型表示单精度32位IEEE 754浮点数。其值的分布范围超出本书的讨论范畴,可参考Java语言规范(Java Language Specification)中的“浮点类型、格式和值”部分。与byte和short类型一样,如果要在浮点型大型数组中存储内存,可以采用该类型(而不用下面的double类型)。该类型不能用于表示精确的值,如货币。要表示精确的值,可以使用java.math.BigDecimal类。第9章将会介绍BigDecimal和其他有用的类。6)double数据类型表示双精度64位IEEE 754浮点数。其值的分布范围超出本书的讨论范畴,可参考Java语言规范中的“浮点类型、格式和值”部分。通常,该数据类型是小数的默认类型。如前所述,也不能用于表示货币等精确值。7)boolean数据类型只有两个可能值:true和false。它主要用于标记true或false条件。该数据类型表示1位信息,但其“大小”并未精确定义。8)char数据类型表示16位Unicode字符。其最小值为'u0000'(或0),最大值为'uffff'(或65 535)。除了这8种基本数据类型外,Java程序语言还提供java.lang.String类支持字符串。将字符串加上双引号会自动创建一个新的String对象,如String s="this is a string";。String对象是不可变的。也就是说,String对象一旦创建,其值就不能改变。就技术而言,String类不是基本数据类型。但考虑到Java对其提供特殊支持,你可能会认为它也是一种基本数据类型。String类的详情参见第9章。1.?默认值字段声明时,不一定总要赋初值。编译器会为那些已经声明但未初始化的字段赋予一个默认值。默认值通常为0或null,这取决于数据类型。但是依赖默认值的做法是一种不好的编程习惯。表3-1总结了上述数据类型的默认值。局部变量的处理方式略有不同,编译器不会为未初始化的局部变量赋初值。如果局部变量在声明时不能初始化,那么使用该局部变量之前必须为其赋值。访问未初始化的局部变量会导致编译时错误。
2.?字大家可能已经注意到,初始化基本类型的变量时不能使用关键字new。基本类型是内嵌在Java语言中的特殊数据类型,它们不需要用类来创建。字(或文字,literal)是用源代码表示的固定值。字不需要计算,直接由代码表示。下面给出为主类型变量指派字的例子:(1)整型字
整型字如果以L或l结尾,就是long类型的;否则就是int类型的。建议使用大写字母L,因为小写字母l与数字1很难区分。byte、short、int和long类型的整数值可以由int类型的字创建。超出int值范围的long类型的值,可以由long类型的字创建。整型字可以由下述记数系统表示:十进制。基数为10,数字由0到9的整数组成。这也是我们日常用的记数系统。十六进制。基数为16,数字由0到9的整数和A到F的大写字母组成。二进制。基数为2,组成数字只有0和1。通常的编程中,十进制系统可能是人们唯一用过的记数系统。如果要用其他数制系统,要注意其语法的正确性,前缀0x表示十六进制数,前缀0b表示二进制数,例子如下。(2)浮点字
浮点字是以字母F或f结尾的float类型的字,或是以字母D或d结尾的double类型的字。浮点字的表示方法有三种:用E或e表示科学记数标记,用F或f表示32位float类型的字,用D或d表示64位double类型的字(默认类型,通常省略)。下划线只能放在数字之间,不能放在下述位置:
数的开头或末尾浮点字中与小数点相邻的位置后缀F或L前面要求是数字字符串的位置下面例子说明数字文字中合法和不合法的下划线放置位置(如黑体所示)。3.1.3 数组
数组是固定数目的单一数据类型值的容器对象。创建数组时要指定其长度。创建后,其长度就固定了。“Hello World!”实例程序的main方法中已经给出了一个数组实例。本小节详细介绍数组。数组中的每个项都称作元素(element),每个元素都用数字索引(index)访问。上述例子清晰地介绍了数组的语法。但真正编写程序时,可能会用循环构造(looping construct)来迭代数组中的元素,而不是上例中为每个元素都写一行代码。循环构造(for、while、do-while)的内容将在3.4节中介绍。
1.?声明变量引用数组上述程序用下面两行代码声明数组anArray:与其他类型的变量声明一样,数组声明也包含两个组件:数组类型和数组名。数组的类型写作type[],其中type是包含的元素的数据类型,方括号表示该变量保存数组。这种写法中没有包含数组大小(这是方括号内为空的原因)。数组名可以是任意名称,只要它满足3.1.1节讨论的命名规则和约定。与其他类型的变量一样,该声明不会创建数组,而只是告诉编译器该变量可用于保存特定类型的数组。类似地,可以声明其他数据类型的数组:
也可以将方括号写在数组名后面:
但是,通常不建议采用这种声明方式。方括号表示数组的类型,应该和类型标记符写在一起。
2.?创建、初始化和访问数组创建数组的一个方法是使用new运算符。下述语句来自ArrayDemo程序,它分配了一个带有10个整型元素内存空间的数组,并将该数组赋值给anArray变量:如果没有这条语句,编译器会报错,并且编译失败:
下面几行代码为数组元素赋值:
数组元素通过数字索引访问:
也可以选用下述快捷方式来定义和初始化数组:
采用这种方式时,数组大小由花括号之间用逗号分隔的值的个数决定。
也可以用两个或多个方括号声明多维数组(multidimensional array),如String[][] names。其元素必须用相应的索引值来访问。Java程序语言中,多维数组是组件也是数组的数组。这一点与C或Fortran语言中的数组不同。因此,每行的长度可以不同,如multiDimArrayDemo程序所示。其输出如下:
最后,可以使用内置的length属性来获取数组的大小。下述代码会将数组大小显示在标准输出上:
3.?复制数组
System类有arraycopy方法,可用于数组之间数据的高效复制:两个Object参数分别指定源数组和目标数组,三个int参数分别指定源数组的起始位置、目标数组的起始位置以及待复制的元素个数。
下述ArrayCopyDemo程序声明char类型的数组,其元素构成单词decaffeinated,并使用System (arraycopy)方法将该数组组件的子序列复制到第2个数组中:输出结果如下:
4.?数组操作
数组是编程中重要且有用的概念。Java SE提供了一系列与数组相关的常用操作方法。例如,ArrayCopyDemo例子使用System类的arraycopy()方法,而不是手动将源数组中的元素依次存入目标数组。该过程在后台完成,开发人员只需使用一行代码调用该方法即可。为方便起见,Java SE在java.util.Arrays类中提供了几个数组操作方法(如复制、排序和查找等常见任务)。例如,可以使用java.util.Arrays类的copyOfRange()方法将前述ArrayCopyDemo方法修改为如下的ArrayCopyOfDemo方法。两者的区别在于,使用copyOfRange()方法时,调用方法之前不需要创建目标数组,该方法会返回目标数组。显然,该例子包含的代码更少,但程序的输出仍然一样,也是caffein。
java.util.Arrays类也提供了其他一些有用的操作方法,例如:binarySearch()——在数组中搜索特定值,并返回其位置索引。equals()——对两个数组进行比较,并确定两者是否相等。fill()——在数组的每个索引位置上填上指定值。升序排序方法——Java SE 8引入两种方法,一种是顺序方法sort(),另一种是并发方法parallelSort()。多处理器系统中大数组的并发排序比顺序排序要快。3.1.4 小结Java程序语言同时采用术语字段和变量。实例变量(非静态字段)对每个类的实例都是唯一的。类变量(静态字段)是用static修饰符声明的字段。不管类有多少个实例,都只有一个类变量。局部变量表示方法内的临时状态。参数是为方法提供附加信息的变量。局部变量和参数通常归类为变量,而非字段。命名字段或变量时,应该(或必须)遵守一些命名规则和约定。八种基本数据类型为byte、short、int、long、float、double、boolean和char。java.lang.String表示字符串。编译器会为这些类型的字段指派一个默认值,但不会为局部变量指派默认值。字(文字)是固定值的源代码表示。数组是固定数目的单一数据类型值的容器对象。创建数组时要指定其长度。创建后,数组长度就固定了。3.1.5 问题和练习:变量问题相关答案参考
。转载地址:http://tomdm.baihongyu.com/