版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
2.1标识符与关键字
2.2简单计算
2.3基本数据类型
2.4运算符
2.5程序流程控制
2.6方法2.7小结2.8习题
1.标识符
Java用标识符(identifier)表示变量名、类名和方法名,它们的命名要符合正确的命名规则,即合法的Java标识符。Java中对正确标识符的规定如下:
(1)标识符必须由字母、下划线“_”或美元符号“$”开头。
2.1标识符与关键字
(2)标识符中的其他字符一定是字母、数字、下划线或美元符号。
(3)标识符的字符中不能有空格。
(4)一个标识符的长度不能超过65535个字符。
Java语言区分字母大小写,所以VALUE、Value、value表示不同的标识符。
2.关键字
关键字(keyword)是Java语言为特殊目的而保留的标识符,程序员不能改变它们,也不能作为一般标识符来使用而赋予别的含义。表2-1列出了Java中的关键字。表2-1Java的关键字关键字const和goto当前并未使用。单词false、null和true都是为特定的目的而保留的,也不可以作变量名。关键字区分大小写,并只由小写字母构成。
再来看一下第1章中的程序EarthToMoon.java。在类头的定义中,有关关键字和标识符的说明如图2-1所示。图2-1定义说明在这个程序中,其他标识符的名字有main、String、args、System、out、println、n和paperThick。标识符main是开始执行程序的方法名;String和System是Java类名;args、out、n和paperThick是可以调用一些程序资源的变量;println是把信息送到控制窗口的方法名。
【例2-1】程序设计的目的是要解决一些实际问题。例如,根据给定的半径计算出圆的面积。这里将π的值始终取为3.14,而半径的值可以不断变化,要求计算并显示结果。
程序Area.java示例。2.2简单计算程序运行结果如图2-2所示。图2-2Area.java的运行结果2.2.1常量
在计算中有一个不发生变化的数据,即π的值被规定为3.14。在程序中用VALUE_PAI这个标识符来表示。
常量是程序初始化内存地址后,其值不能再改变的内存地址的符号名称,它必须是正确的Java标识符。
计算中使用常量之前,必须先定义和初始化常量。常量的定义常常采用图2-3所示的形式。图2-3常量定义的形式在如下程序中,将VALUE_PAI定义为double类型的常量。(关于double类型的具体细节将在2.3节中讨论。)
finaldoubleVALUE_PAI=3.14;
上述语句把VALUE_PAI与存放double类型数据3.14的内存地址关联起来。由于使用了修饰关键词final,在程序执行过程中,地址中的内容是固定的;关键词double表明定义的常量是double类型的值。从这时起,在方法main()中,VALUE_PAI与double值3.14是完全对应的。图2-4描绘了定义的结果(用锁来表示不可变更的值)。图2-4常量的定义结果
Java允许在一条语句中定义多个常量,之间用逗号分开。例如,下面的语句定义了两个常量。
finaldoubleHEIGHT=500,WIDTH=150;
这种方式没有单一语句那样突出,且妨碍了注释。考虑到程序的可读性,一般不鼓励这种方式定义常量。
另外,Java编程中有一个习惯,常量标识符的名字采用大写字母,单词之间用下划线隔开,且名称对其目标要具有描述性。例如,用VALUE_PAI来表示π。2.2.2变量
程序Area.java中除了使用常量,还使用了double类型的变量。变量是程序执行过程中,内容可以改变的内存地址的符号名字。
使用变量的原则是“先说明后使用”,即变量在使用前必须先声明,以便计算机留出相应大小的存储空间,用来存放在程序执行过程中发生改变的数据。基本的变量定义通常采用图2-5所示的形式。图2-5变量定义的形式程序中,radius、area都是double类型的局部简单变量。因为在定义中没有修饰符final,所以它们是变量;因为对它们的使用仅限于定义它们的方法,所以它们是局部变量。
doubleradius=2.5;
即变量radius初始化为double类型,值为2.5。radius定义的结果如图2-6所示。因为radius的值可以改变,因此在它的描述中没有锁。图2-6变量的定义结果如果没有初始值,局部变量就没有被初始化。对于下面这条语句:
doubleradius;
其定义结果如图2-7所示。图2-7无初始值变量的定义结果其中“-”表示未被初始化的值。尽管定义变量的时候可以不做初始化,但Java编译器要求所有变量在使用之前必须初始化。否则在使用未初始化变量时,编译出错。
一条语句可以定义多个变量,其间用逗号分开。下面的语句就采用这种风格定义并初始化变量weightInPounds(体重:用英镑度量)和heightInFeet(身高:用英尺度量)。
doubleweightInPounds=70.5,heightInFeet=4.2;如果考虑程序的可读性,比较好的定义风格是一条语句定义一个变量。
另外,Java编程对变量的命名也遵循一定的习惯。变量标识符的名称应该能描述它所代表的值,而且由小写字母开始。如果变量名字仅由一个单词构成,那么整个名字都小写,如radius、area;如果变量名字由多个单词构成,那么这些单词连在一起,除了相连单词(不包括第一个单词)的第一个字母,其余字母都是小写,如weightInPounds、heightInFeet等具有描述性的变量。2.2.3操作
先看程序Area.java中的一条语句:
doublearea=VALUE_PAI*radius*radius;
这条语句有以下几个含义:
(1)定义了一个变量area,并进行了初始化。
(2) VALUE_PAI*radius*radius是一个表达式。
(3)将表达式VALUE_PAI*radius*radius的值赋给变量area。
(4) area=VALUE_PAI*radius*radius;是一条赋值语句。在这条赋值语句中出现了符号“*”,它表示算术运算中的乘法,被称为算术运算符。可以推知,诸如“+”、“-”、“/”等能实现算术运算的符号都称作算术运算符。
那么什么是表达式呢?
表达式是算法语言的基本组成部分,它表示一种求值规则,通常由操作数、运算符和圆括号组成。操作数是参加运算的数据,可以是常数、常量、变量或方法引用,如VALUE_PAI和radius,且出现的变量名必须已经被初始化(值为2.5)。表达式按照运算符的优先级进行计算,求得一个表达式的值。运算符中圆括号的优先级最高,运算次序是“先内层后外层”,因此先计算由圆括号括起来的子表达式。圆括号还可以多级嵌套。
Java规定了表达式的运算规则,对操作数类型、运算符性质、运算结果类型及运算次序都做了严格的规定,程序员使用时必须严格遵循系统的规定,不得自定义。
在变量area的定义中用表达式VALUE_PAI*radius*radius的值来初始化。表达式用了double类型的乘法操作符 *,将常量VALUE_PAI与两个变量radius相乘,结果表示圆的面积。程序的下一部分向用户显示关于圆的信息,这部分由两个println()调用组成。
//显示结果
System.out.println(“Theradiusis:”+radius);
System.out.println(“Theareaofthiscircleis:”+“
”+area);
第一个println()方法调用的功能是:把表达式 "Theradiusis:"+radius的值提供给println()。对于操作符“+”而言,当它的两个操作数都是数值型时,操作符执行加法;当其中至少一个操作数是字符串(String)类型时,操作符执行String连接。
“Theradiusis:”和radius求值,因为radius的值是2.5,连接生成了一个值为 “Theradiusis:2.5”
的字符串,这个值成为println()调用的真正参数。这条语句执行之后,程序输出:
Theradiusis:2.5
与此类似,在执行下一个println()方法调用时:首先"Thearea
ofthiscircleis:" 和 ""求值,连接生成了值为 "Theareaofthiscircleis:"的字符串;然后该值与变量area连接,由于area的值在初始化时通过计算、赋值已经确定为19.625,因此生成字符串的值为 "Theareaofthiscircleis:19.625"。在这之后,程序输出如下:
Theradiusis:2.5
Theareaofthiscircleis:19.625
至此,程序Area.java显示了常量、变量的作用和一些基本操作。
Java的数据类型分为两种,分别是基本类型和引用类型。
(1)基本类型(primitive):包括整数、字符、浮点和布尔等类型。
(2)引用类型(reference):包括数组、类和接口等类型。如按钮、窗口等控件属于引用类型变量。
2.3基本数据类型
Java在处理这两种类型的数据时,在存储机制上采用了不同策略。Java将引用类型的对象通过new关键字存储在“堆”里,但这种方式对于特别小的、简单的变量,不是很有效。因此,对于这些类型需要特殊对待:通过创建一个并非“引用”的“自动”变量,使得变量拥有“值”,并置于堆栈中,使之更加高效。这些需要特殊对待的类型就是Java中的基本类型。
Java的基本类型包括整型、字符型、浮点型和布尔型四类,每一类称为一种数据类型(datatype)。数据类型定义了数据的性质、取值范围、存储方式以及对数据所能进行的运算和操作。程序中的每一个数据都属于一种类型,确定了数据的类型也就相应地确定了数据的性质以及对数据进行的操作,同时数据也受到类型的保护,确保了数据不被非法操作。
Java定义的基本数据类型,它们的分类及关键字如下:
整型:byte、short、int、long。
字符型:char。
浮点型:float、double。
布尔型:boolean。
可以看出,Java设置了多种数据类型,如byte、short、int和long,float和double。这样做的目的是让程序员能充分地利用特定的计算机硬件(如PCs、移动电话、PDAs)所支持的各种类型。Java需确定每种基本类型所占存储空间的大小。它们的大小并不像其他大多数语言那样随机器硬件架构的变化而变化。这种所占存储空间大小的不变性是Java程序具有可移植性的原因之一。2.3.1整数类型
Java定义了四种表示整数的整型:字节型(byte)、短整型(short)、整型(int)、长整型(long)。它们的特性如表2-2所示。表2-2整数类型一个整数隐含为整型(int)。当要将一个整数强制表示为长整数时,需在后面加L或l。
Java的整数有三种进制的表示形式:
十进制:用多个0~9之间的数字表示,如123和 -100,其首位不能为0。
八进制:以字母0打头,后跟多个0~7之间的数字,如0123。
十六进制:以字母0x或0X打头,后跟多个0~9之间的数字或a~f之间的小写字母以及A~F之间的大写字母,a~f或A~F分别表示值10~15,如0X123E。
关于int类型的操作在程序CelToFah.java中得到了演示。
【例2-2】整数摄氏温度到整数华氏温度的转换。转换公式为:Fahrenheit=32+(9/5)
Celsius。
publicclassCelToFah
{
publicstaticvoidmain(String[]args)
{//设置将被转换的摄氏温度
intcelsius=32;//转换成相应的华氏温度
intfahrenheit=32+((9*celsius)/5);
//显示结果
System.out.println("Celsiustemperatureis:"+celsius);
System.out.println("equalsFahrenheittemperatureis:"+fahrenheit);
}
}
程序运行结果如图2-8所示。图2-8CelToFah.java的运行结果2.3.2字符类型
字符型(char)用来存储字符。一个字符用一个16位的Unicode码表示。所有可见的ASCII字符都可以用单引号括起来成为字符,如 'a'、'A'、'#' 等。关于字符类型的特性如表2-3所示。表2-3字 符 类 型通常,程序员并不是用数字来表示字符,而是用单引号表示字符,编译器会自动将字符表达翻译成Unicode编码。比如,当程序员需要使用字母a时,用'a'而不是它的Unicode值97。由于char的表达本质上是整数,所以对整数定义的操作符也可以用于char变量和值。
Unicode字符集编码按照值的大小有以下规则:
(一)顺序规则
‘0’<‘1’<‘2’<…<‘9’
‘a’<‘b’<‘c’<…<‘z’
‘A’<‘B’<‘C’<…<‘Z’
(二)计算规则
对除9以外的任何数字d,表达式'd'+1都生成下一个数字的字符。例如,'7'+1生成'8'的Unicode值56。
对除z以外的任何小写拉丁字母d,表达式‘d’+1都生成下一个小写字母的字符。例如,‘b’+1生成‘c’的Unicode值99。
对除Z以外的任何大写拉丁字母D,表达式‘D’+1都生成下一个大写字母的字符。例如,‘O’+1生成‘P’的Unicode值80。
这些关系可以使字符按照它所代表的是小写字母、大写字母或数字来有效地分类。
关于上述char类型的性质,程序LowerToUpper.java给出了演示。
【例2-3】把一个小写字母转换成与它对应的大写字母。publicclassLowerToUpper
{
publicstaticvoidmain(String[]args)
{//设置相关的小写字母
charlowerLetter='h';
//转换成大写字母
intupperLetter=‘A’+(lowerLetter-‘a’);
//显示结果
System.out.println(“Lowercaseis:”+lowerLetter);
System.out.println(“Uppercaseis:"+(char)upperLetter);
}
}
程序运行结果如图2-9所示。
另外,还有一些控制字符不能直接显示,可以利用转义序列来表示,如表2-4所示。图2-9LowerToUpper.java的运行结果表2-4转义序列
【例2-4】关于转义序列的用法,参考程序CharOfChange.java。
publicclassCharOfChange
{
publicstaticvoidmain(String[]args)
{
//单引号前面可以不加\,直接输出
System.out.println("Hesaid,\"Let’sstudycharof'\\'\"");
}
}
程序运行结果如图2-10所示。图2-10CharOfChange.java的运行结果2.3.3浮点类型
Java用浮点型表示数学中的实数,包括整数部分和小数部分。浮点数用于需要小数位精确度的计算。例如,计算平方根或三角函数等,都会产生浮点型的值。浮点型有float(32位)和double(64位)两种类型,分别称作单精度型和双精度型,其格式完全遵循IEEE754标准。关于浮点类型的特性如表2-5所示。表2-5浮点类型浮点数有两种表示方式。
标准计数法:由整数部分和小数部分构成,中间有小数点分开。整数部分或小数部分其中之一可以为空,如123.456、1.、.9、0.0等。
科学计数法:由十进制整数、小数点、小数和指数部分构成,指数部分由字母E或e加幂表示,如1.2345E+2、0.23E-4、-45.e+23、23.68E12都是用科学记数法表示的浮点数,它们依次等于1.2345×102、0.23×10-4、-45×1023、23.68×1012。
一个浮点数隐含为double型。在一个浮点数后加字母F或f,可将其强制转换为float型。
【例2-5】程序RealDemo.java演示浮点数的使用。
publicclassRealDemo
{
publicstaticvoidmain(String[]args)
{//对于float变量进行赋值,小数后面必须加上f
floatx=123.456f;//对于double变量进行赋值,小数后面不一定需要加上d
doubley1=23.789;
doubley2=78.654d;
//显示结果
System.out.println("x="+x);
System.out.println("y1="+y1);
System.out.println("y2="+y2);
}
}
程序运行结果如图2-11所示。图2-11RealDemo.java的运行结果2.3.4布尔类型
布尔型(boolean)用来表示逻辑值,也称为逻辑型。boolean是以19世纪英国数学家GeorgeBoole的名字命名的,正是他使逻辑值的研究正式化。boolean类型有真(true)和假(false)两个值,并且这种类型所占存储空间的大小没有明确定义,仅定义为能够取字面值true或false。true和false不能转换成数字表示形式。
所有关系运算(如a<b)的返回值都是布尔型的值,可以利用布尔型的值控制语句中的条件表达式,如if、while、for等语句。
2.2节通过分析一个简单计算的操作过程,初步明确了运算符与表达式的概念。在程序中,涉及了算术运算符“*”和赋值运算符“=”,并且分析了表达式的求值过程。
在实际操作中,Java定义了各种运算操作,并提供了丰富的运算操作符。当一个表达式中存在多个操作符时,就需要考虑各部分的计算顺序。而这个顺序就由操作符的优先级和结合规则来确定。因此在学习Java的运算符操作之前,必须先对优先级有一个初步的掌握。2.4运算符2.4.1优先级
先看一条语句:
intx=3*5/2;
按照整型的计算规则,结果是7还是6呢?这取决于表达式的计算顺序。如果按照(3*5)/2的顺序计算,结果是7;如果按照3*(5/2)的顺序计算,结果是6。由于在算术运算中乘法与除法的运算级别相同,在没有设定括号的前提下,表达式按照自左向右(被称为“左结合”)的顺序计算,因此语句的执行结果是7。大多运算符按照从左向右的次序进行计算,少数运算符的运算次序是从右向左的(被称为“右结合”),如赋值运算符、三元条件运算符等,后面将进行讲解。再看下面的表达式:
4/2+8 //除法优先级高于加法
-4*8 //取反优先级高于乘法
12+15%/2 //取余数优先级高于加法
Java对操作符的优先级做了严格的规定,程序员使用时必须严格遵循系统的规定,不得自定义。括号可以用来改变计算的顺序。例如:
inta=x+y-2/2+z;
为上述表达式加上括号后,就有了不同的含义:
inta=x+(y-2)/(2+z);
可以想象,利用括号的嵌套,可以完成更为复杂的运算关系,如:
inta=(2+(3+5)*10)/(6-4);先计算子表达式(3+5),然后再计算外层括号中的表达式,结果为41。
另外,需要注意的用法是,括号经常在不必需的地方使用,以明确运算顺序。这个技巧更易于读者理解程序代码。例如,表达式x*y+x/y-z和带括号的表达式(x*y)+(x/y)-z进行同样的计算,但是后者具有更加明确的意思。2.4.2赋值运算符
1.赋值运算
赋值运算的作用是使变量获得值。赋值的格式如下:
<变量名>=<表达式>
其中,“=”是赋值运算符,它有两个操作数(“=”被称为二元操作符):左边的操作数是目标变量;右边的操作数是表达式。运算时,赋值操作符根据表达式的结果更新与目标变量对应的内存地址中的值,即先计算<表达式>的值,再将表达式的结果值赋给<变量名>。因此,赋值的运算次序是从右向左的,即“右结合”。
表2-6执行了一系列赋值语句,每条语句执行后,变量对应的内存发生了变化,直观地体现了赋值语句的执行过程。表2-6赋值语句的执行过程
2.赋值运算的语法错误
赋值中的变量名必须已声明,而且表达式必须能计算出确定的值,否则将产生编译错误。例如,程序FuZhi1.java和程序FuZhi2.java分别验证了这些要求。
【例2-6】FuZhi1.java程序。
publicclassFuZhi1
{
publicstaticvoidmain(String[]args)
{
k=10;
System.out.println(“k=”+k);
}
}
当k声明时,系统将产生“不能解析符号”的编译错误,程序运行结果如图2-12所示。图2-12FuZhi1.java的运行结果【例2-7】FuZhi2.java程序。
publicclassFuZhi2
{
publicstaticvoidmain(String[]args)
{
inti,k;
k=i+10;
}
}
由于变量i没有具体的值,不能参加运算,系统将产生“变量i可能还未被初始化”的编译错误,程序运行结果如图2-13所示。图2-13FuZhi2.java的运行结果
3.赋值的优先级和结合律
先看下面这条赋值语句:
x=9*10;
赋值操作符会产生一个值,这个值被看做是赋值操作的值,即左操作数(x)的新值。假设x和y是已经定义好的int变量,此赋值语句之前的语句计算出15,又把15存储在变量x中。由于赋值生成了一个值,进而可以写出下面的表达式:
y=x=9*10;这个赋值表达式意味着什么呢?关键在于对赋值操作符优先级与结合律的理解。正确的编译是9与10先作乘法,于是“=”的优先级低于“*”,因此,上面的表达式编译为:
y=x=(9*10);
再观察x的两边都有赋值操作符“=”,这种情况下,“=”的结合律决定了x是与右边的“=”先结合,还是与左边的“=”先结合。由于赋值操作符是右结合的,因此,表达式的正确编译为:
y=(x=(9*10));
它表明将赋值操作x=(9*10)的值90赋给变量y,于是赋值操作y=(x=(9*10))的值是90。
4.复合赋值
语句“i=i+5;”完成的功能很简单,即取出变量i中的值,再加上5,将结果再存储到变量i中。
Java有一个完成同样功能的复合加法运算,写作:
i+=5;
“+=”是一种特殊的操作符,用它进行常见的操作,可以认为是编程语言的简化。其他一些复合赋值操作符是-=、*=、/=、%=,它们依次对目标变量进行减法、乘法、除法和求余运算,再把值赋给目标变量。
将复合运算的概念进行延伸,可以涉及到其他的运算操作,如表2-7所示。表中涉及到的运算将在接下来的内容中进行讲解。表2-7赋值运算符与其他运算符的简捷使用方式
5.赋值相容
如果目标变量与表达式的类型是相同的,就可以赋值,称为类型相同。如果两者类型不相同,并且目标变量类型比表达式类型长时,系统会自动将表达式转化为较长的类型,如int型转化为long型,这时也可以赋值,称为赋值相容(assignmentcompatible)。
例如:
longbigValue=99L;//类型相同
longbigval=6;
//6是int型,自动转化为long型,赋值相容
doublez=12.414F //12.414F是float型,赋值相容如果变量类型比表达式类型短,则赋值不相容,编译时产生“可能存在的精度损失”的错误。例如,
intsmallval=99L //99L是long型,赋值不相容
floatz1=12.414; //12.414是double型,赋值不相容
赋值不相容时,需要使用强制类型转换,其格式如下:
(<目标类型>)<表达式>
例如,
i=(int)99L;
//数值的转换
intj=(int)(bigValue); //变量的转换
将long型转换为int型后,可以赋值。2.4.3算术运算符
Java的算术运算符分为一元运算符和二元运算符。一元运算符只有一个操作数,而二元运算符有两个操作数参加运算。
1.一元运算符:一元正(+),一元负(-)
inti=10,j,k;
j=+i; //取i的原值,则j=10
k=-i; //取与i相反符号的值,则k=-10一元运算符与操作数之间不允许有空格。
编译器能正确识别下面的这条语句:
k=5*-i;
执行结果是-50。但读者在阅读程序的时候会感到费解,所以最好明确地写成:
k=(5*-i);
2.二元运算符:加(+),减(-),乘(*),除(/)和取余(%)
其中,+、-、*、/完成加、减、乘、除四则运算,%则是求两个操作数相除的余数。这五种运算符均适用于整型和浮点型。当在不同数据类型的操作数之间进行算术运算时,所得结果的类型与精度最高的那种类型一致。程序SuanShu.java列举了算术运算中的典型操作,下面请仔细分析其运行结果。
【例2-8】SuanShu.java程序。publicclassSuanShu
{
publicstaticvoidmain(String[]args)
{
System.out.println("3*4="+3*4);
System.out.println("3*4.0="+3*4.0);
System.out.println("15/2="+15/2);
System.out.println("15.2/2="+15.2/2);
System.out.println("7%2="+7%2);
System.out.println("-7%2="+-7%2);
System.out.println("7%-2="+7%-2);
System.out.println("7.0%2="+7.0%2);
}
}
程序运行结果如图2-14所示。图2-14SuanShu.java的编译结果从结果中可以得到一些运算规则:
(1)整数除法会直接去掉结果的小数位,而不是四舍五入地求整数位。
(2)整数求余,其结果的符号与被除数相同。
(3)求余操作数中只要有浮点数,结果即为浮点数。
3.一个小应用
用变量w表示今天是星期几,对应关系如表2-8所示。假设w=1表示今天是星期一,如何利用w表示明天(星期二)和昨天(星期天)。表2-8w与星期几的对应关系利用整数求余就可以很容易地解决这个问题,解决办法如下:
tomorrow=(w+1)%7; //值为2:明天
yesterday=(w-1+7)%7; //值为0:昨天
根据这道题的解决思路,可以考虑:怎样表示月份的上一个月和下一个月?2.4.4类型转换
在前面的讲解中,已经涉及到了数值表达式中的操作数为不同类型的情况,并且我们对类型的转换作了简单介绍。现在对类型转换再进行一些系统的讨论。
如果加法的一个操作数是int型,另一个操作数是char型,如何计算?或者,乘法的一个操作数是int型,另一个操作数是double型,又如何计算?这就需要进行类型转换。Java有两种转换基本类型的方法:自动提升和强制转换。
1.自动提升
Java在进行任何运算之前,编译器在必要的时候会自动进行类型的提升。
程序TypeAutoUpdate.java对七种基本类型进行了两两运算,从结果就可以看出系统在运算的时候,进行了类型转换。
【例2-9】TypeAutoUpdate.java程序。publicclassTypeAutoUpdate
{
publicstaticvoidmain(String[]args)
{byteb=100;
charc='a';
shorts=1000;
inti=40000;
longl=20000L;
floatf=25.4f;
doubled=5.5;
doubleresult=(f*b)+(l*f)+(i/c)+(d*s);System.out.println("f*b(25.4f*100)="+f*b);
System.out.println("l*f(20000L*25.4f)="+l*f);
System.out.println("i/c(40000/'a')="+i/c);
System.out.println("d*s(5.5*1000)="+d*s);
System.out.println("result="+result);
}
}
程序运行结果如图2-15所示。图2-15TypeAutoUpdate.java的执行结果对于结果,有以下几点说明:
(1)计算(f*b)时,b自动提升为float型。
(2)计算(l*f)时,l自动提升为float型。
(3)计算(i/c)时,c自动提升为int型。
(4)计算(d*s)时,s自动提升为double型。
(5)再相加时,中间结果都变为double型,所以result只能声明为double型,声明为其他类型就会出错。通常,表达式中出现的最大的数据类型决定了表达式最终结果的数据类型。
(6) Java允许把任何基本类型转换成别的基本数据类型,但布尔型除外,因为它根本不允许进行任何类型的转换处理。
自动提升的规则如下:
(1)所有的byte型和short型的值被提升到int型。
(2)整数运算时,如果有一个运算数是long型,则其他运算数的值都被提升到long型。
(3)浮点运算时,如果有一个运算数是float型,则其他整数值都被提升到float型。
(4)浮点运算时,如果有一个运算数是double型,则其他运算数的值都被提升到double型,计算结果也是double型。类型的自动提升发生的条件是:两种类型是兼容的,或者目标类型的范围比原类型的范围大。
当目标类型的范围能容纳原类型的信息时,不会造成任何信息的丢失,这种转换被称为“扩展转换”(wideningconversion)。然而如果要执行一种名为“窄化转换”(narrowingconversion)的操作,即目标类型的范围不能容纳原来类型的信息时,就有可能面临信息丢失的危险。此时,编译器会强制我们进行类型转换。
2.强制转换
除自动提升情况之外,要想转换数据类型,需要进行强制类型转换。强制类型转换的方法是:在数据前放一对包括新的类型名的括号,其格式如下:
(目标类型)<表达式>
如语句“inti=(int)66666L;”表示将long型的66666L转换成int型,然后赋给变量i。阅读程序ForceChange.java,分析结果。
【例2-10】ForceChange.java程序。publicclassForceChange
{
publicstaticvoidmain(String[]args)
{
doubled=390.456;
floatf=(float)d;
longl=(long)d;
inti=(int)d;
shorts=(short)d;
byteb=(byte)d;
System.out.println("d=390.456");
System.out.println("(float)d="+f);
System.out.println("(long)d="+l);
System.out.println("(int)d="+i);
System.out.println("(short)d="+s);
System.out.println("(byte)d="+b);
System.out.println("(char)65="+(char)65);
}
}
程序运行结果如图2-16所示。图2-16ForceChange.java的执行结果2.4.5自增与自减运算符
递增和递减运算是两种相当不错的快捷运算(常称作“自动递增”和“自动递减”运算)。其中,递减操作符是“--”,意思是“减少一个单位”;递增操作符是“++”,意思是“增加一个单位”。比如,若定义“inti=10;”,则++i就等价于“i=i+1”。递增和递减操作符不仅改变了变量,并且以变量的值作为生成的结果。这两种操作符各有两种使用方式,通常称为“前缀式”和“后缀式”。“前缀式”表示运算符位于变量或表达式的前面,如++j、--j;“后缀式”表示运算符位于变量或表达式的后面,如j++、j--。那么前缀形式与后缀形式有什么区别呢?看下面两段代码的执行结果。
代码一:
inti=10;
System.out.println(i++);//结果:10
代码二:
inti=10;
System.out.println(++i);//结果:11为什么结果是这样呢?原因是:对于前缀式使用方式而言,先执行变量的递增或递减运算,再返回生成的值参与其他运算;对于后缀式使用方式而言,先返回变量的原值参与其他运算,再执行变量的递增或递减运算。
表2-9执行了一系列递增递减语句,观察语句执行后变量所对应内存发生的变化,并分析运行结果。表2-9递增递减语句的执行过程从执行结果可以看出:++i(++j)返回变量增加后的值,j--返回变量减少之前的值。
但是在编程时,切忌不恰当地使用递增和递减运算符,使得程序变得很费解。像下面的语句:
intk=5+i++*++j;
下面的代码段与它是等同的,但是比它容易理解多了。
++j;
intk=5+(i*j);
++i;2.4.6关系运算符
关系运算符用于比较两个值之间的大小,结果返回布尔值,它们计算的是操作数的值之间的关系。如果关系是真的,关系表达式会生成true(真);如果关系不真实,则生成false(假)。关系运算符有6种:等于(==)、不等于(!=)、大于(>)、大于等于(>=)、小于(<)和小于等于(<=),例如:
3<=2; //结果:false
‘A’<‘a’; //结果:true
阅读程序RelationOperate.java,分析结果。【例2-11】RelationOperate.java程序。
publicclassRelationOperate
{
publicstaticvoidmain(String[]args)
{
intx=9,y=11;
booleanresult;
System.out.println("x="+x+"y="+y);
System.out.println("x==y"+(x==y));
System.out.println("x!=y"+(x!=y));
System.out.println("x<y"+(x<y));
System.out.println("x<=y"+(x<=y));
System.out.println("x>y"+(x>y));
System.out.println("x>=y"+(x>=y));
result=((x!=y)==true);
System.out.println("x!=y"+result);
}
}
程序运行结果如图2-17所示。图2-17RelationOperate.java的执行结果在使用“==”运算符时,程序员会犯一个常见的错误,如下面的程序:
while(x=y){
…
}
尽管还没有学习程序结构设计,但从语意上可以推断:程序员很明显是想测试是否相等(==),而不是进行赋值操作(=)。在Java中,赋值操作的结果并不是布尔值,而编译器期望的是一个布尔值。由于Java不会自动地将int数值转换成布尔值,所以在编译时会抛出一个错误,阻止程序进一步运行。2.4.7逻辑运算符
逻辑运算符只能处理布尔值,所得结果也都是布尔值。Java的逻辑操作符有:“与”(&&)、“或”(||)、“非”(!)。它们能根据参数的逻辑关系,生成一个布尔值。逻辑运算符的真值表如表2-10所示。表2-10逻辑运算符的真值表例如:
out.println((i>0)&&(i<9)); //判断i值是否在0~9之间
System.out.println((ch=='A')||ch=='a'); //判断ch是否为字母A或a
另外,&&和||运算符还有一个有趣的属性——“短路”现象(short-circuit)。对于&&运算符而言,从左向右依次逐个计算条件是否成立,一旦发现有一个条件不成立,就立即终止计算并且得到复合条件的结果值为false,不再计算余下的条件是否成立,因此表达式靠后的部分有可能不会被运算。同样,对于||运算符而言,从左向右依次逐个计算条件是否成立,一旦发现有一个条件成立,就立即终止计算并且得到复合条件的结果值为true,不再计算其余的条件。例如有3个用&&连接的表达式,当计算第一个为false时,那么整个逻辑表达式为false,其余的两个表达式将不再计算。程序ShortCircuit.java表明了这一点。【例2-12】ShortCircuit.java程序。
publicclassShortCircuit
{
publicstaticvoidmain(String[]args)
{
intn=5;
intm=8;
System.out.println("compareresultis:"+((n>m)&&(++n)>m));
System.out.println("nis"+n);
System.out.println("compareresultis:"+((n<m)&&(++n)>m));
System.out.println("nis"+n);
System.out.println("compareresultis:"+((n<m)||(++n)>m));
System.out.println("nis"+n);
}
}
程序运行结果如图2-18所示。图2-18ShortCircuit.java的执行结果对结果进行分析如下:
(1)程序首先计算下面的表达式:
(n>m)&&(++n)>m
因为n>m为false,因此整个表达式为false,程序不再计算(++n)>m,所以n仍然为5,没有机会增加1了。
(2)程序接着计算下面的表达式:
(n<m)&&(++n)>m因为n<m为true,无法确定整个逻辑表达式的值,所以要接着计算(++n)>m的值,无论结果怎样,n的值终于加1成为6。
(3)程序最后计算下面的表达式:
(n<m)||(++n)>m)
因为n<m为true,因此整个表达式为true,程序不再计算(++n)>m,所以n仍然为6,没有机会增加1了。2.4.8位运算符
位运算是对整数基本数据类型中的单个“比特”(bit)进行操作,是对数据进行按位操作的手段。位运算符对两个参数中对应的位执行布尔代数运算,并最终生成一个结果。Java的位运算符有:非(~)、与(&)、或( | )、异或( ^ )。位运算符的真值表如表2-11所示。表2-11位运算符的真值表例如:
6|2=6 等价于二进制 0110|0010=0110
4&2=0 等价于二进制 0100&0010=0000
6^2=4 等价于二进制 0110^0010=0100
~4=-5 等价于二进制 ~00000100=11111011
现在来做一个小测试:一个值的第3位是否被设置成了1?
解决思路:用1和第3位作与运算,用0和其余位作与运算,观察结果。如果结果是0,第3位是0,否则,第3位被置成1。阅读程序BitOperate.java,运行结果如图2-19所示。【例2-13】BitOperate.java程序。
publicclassBitOperate
{
publicstaticvoidmain(String[]args)
{intx=12;
//8的二进制表示为00001000(满足第3位是1,其余位是0的条件)inttest=8;
intresult=x&test;
if(result==0)
System.out.println("Bit3isnotset.");
if(result!=0)
System.out.println("Bit3isset.");
}
}图2-19BitOperate.java的执行结果当&、^和|操作符处理布尔值true/false时,它们被看做是位逻辑运算符。位逻辑运算符和位运算符的工作方式相同(用false代替0,true代替1)。真值表如表2-12所示。表2-12位逻辑运算符的真值表与表2-10做一个比较会发现:位逻辑运算符和逻辑运算符在“与”、“或”的运算规则上完全相同。那么它们在使用上有什么差别呢?前面讲过,&& 和 || 运算符具有“短路”现象,而&和|运算符没有这种现象。在计算表达式的值的时候,它们会做完所有的运算,再返回整个逻辑表达式的值。将程序ShortCircuit.java进行改写,比较一下结果。
【例2-14】改写后的ShortCircuit.java程序。publicclassShortCircuit
{
publicstaticvoidmain(String[]args)
{
intn=5;
intm=8;
System.out.println("compareresultis:"+((n>m)&(++n)>m));
System.out.println("nis"+n);
System.out.println("compareresultis:"+((n<m)|(++n)>m));
System.out.println("nis"+n);
}
}
程序运行结果如图2-20所示。图2-20改写后的ShortCircuit.java的执行结果2.4.9移位运算符
使用移位操作符可以将一个数字的所有位向左或者向右移动指定数目的二进制位。Java提供的移位运算符有:右移位(>>)、无符号右移位(>>>)、左移位(<<)。
右移位运算符考虑操作数的符号,因为负值意味着最左边一位是1,向右移位负数将在左边产生一个新的1。如果希望操作数字实际的位,并在移位负数时不在左端附加1,使用无符号右移位运算符(>>>,也称为零填充右移位运算符)。不管被移位的数字是正还是负,它在左端产生一个0,例如:
9>>2=11001右移2位为0010
1<<2=40001左移2位为0100
程序MoveBit.java演示了移位操作,运行结果清楚地表明了操作规则。
【例2-15】MoveBit.java程序。
publicclassMoveBit
{
publicstaticvoidmain(String[]args)
{
inta=12;
intb=-12;
inttemp;
System.out.println("12的二进制表示:"+Integer.toBinaryString(a));
temp=12>>1;//结果:6
System.out.println("12>>1:"+Integer.toBinaryString(temp));
temp=12<<1;//结果:24
System.out.println("12<<1:"+Integer.toBinaryString(temp));
System.out.println("-12的二进制表示:");System.out.println(""+Integer.toBinaryString(-12));
temp=-12>>1;//结果:-6
System.out.println("-12>>1:"+Integer.toBinaryString(temp));
temp=-12>>>1;//结果:2147483642
System.out.println("-12>>>1:"+Integer.toBinaryString(temp));
}
}
程序运行结果如图2-21所示。图2-21MoveBit.java的执行结果2.4.10三元条件运算符
三元运算符(?:)比较特别,它有三个操作数:一个条件和两个值。定义形式如下:
boolean-exp?value1:value2
该运算符的作用是:如果“boolean-exp”(布尔表达式)的结果为true,就计算“value1”,而且这个计算结果也就是运算符最终产生的值;如果“boolean-exp”的结果为false,就计算“value2”,同样,它的结果也就成为运算符最终产生的值。例如:
inta=1,b=2,max;
max=a>b?a:b; //max获得a,b之中的较大值
System.out.println(“max=”+max); //输出结果为max=2
现在来看一个小实例:将一个0~15之间的整数转换为十六进制数,并显示出来。
三元运算符解决这个问题很理想,可以用它返回需要的值:如果这个数小于10(x<10),返回该数据对应的字符值('0'+x);否则,将这个数转换成十六进制字母所对应的字符值('a'+(x-10))。该功能由程序ThreeElementOperate.java完成。【例2-16】ThreeElementOperate.java程序。
publicclassThreeElementOperate
{
publicstaticvoidmain(String[]args)
{
intx=14;
intresult=(x<10)?('0'+x):('a'+(x-10));
System.out.println(x+"=0x"+(char)result);
}
}
程序运行结果如图2-22所示。图2-22ThreeElementOperate.java的执行结果2.5.1顺序结构
1.结构说明
一般情况下,顺序结构的程序按语句的书写次序依次顺序执行(sequentialexecution),如图2-23所示。先执行<语句或块A>,再执行<语句或块B>。这种结构的程序具有线性属性,对于解决简单的问题已经足够了。顺序结构是最简单的一种基本结构。2.5程序流程控制图2-23顺序结构示意图
2.应用举例
【例2-17】求一个三位数的数字之和。
首先求得这个三位数的个、十、百位上的数字,将各位数字相加就是该三位数的数字之和。程序清单如下:
publicclassDigSum3
{
publicstaticvoidmain(String[]args)
{
intn=123;
inta=0,b=0,c=0;
intdigsum=0;
a=n%10; //a:个位
b=(n%100)/10; //b:十位
c=n/100; //c:百位
digsum=a+b+c;图2-24DigSum3.java的执行结果
System.out.println("Digsum("+n+")="+digsum);
}
}
程序运行结果如图2-24所示。图2-24DigSum3.java的执行结果
【例2-18】判断一个年份是否为闰年。
根据天文历法规定,每400年中有97个闰年。凡不能被100整除但能被4整除的年份,或能被400整除的年份是闰年,其余年份是平年。如1996、2000是闰年,而1900是平年。
本例演示布尔型的运算。对一个年份year,按上述条件进行判断,即进行相应的逻辑运算,得到布尔型结果值并输出。程序清单如下:
publicclassLeapJudge
{
publicstaticvoidmain(String[]args)
{
intyear=2008;
booleanleap=false;
leap=(year%400==0)||(year%100!=0)&&(year%4==0);
System.out.println(year+"isaleapyear:"+leap);
}
}
程序运行结果如图2-25所示。图2-25LeapJudge.java的执行结果2.5.2分支结构
1.结构说明
程序中有些语句的执行是有条件的。当某条件成立时,执行一段程序;该条件不成立时,执行另一段程序,或不执行,这种情况称为“二路分支结构”,如图2-26所示。在此结构中有一个菱形的判断框,它有两个分支,根据条件<布尔表达式>是否成立(true/false)而分别执行<语句A>或<语句B>。除此之外还有多路分支结构,将在switch控制语句中讲解。图2-26二路分支结构示意图
2.if-else语句
if-else语句是控制程序流程的最基本的形式,其中的else是可选的,所以可按下述两种形式来使用if:
if(Boolean-expression)
statement
或
if(Boolean-expression)
statement
else
statement
其中:if和else是关键字;Boolean-expression是条件表达式,它必须产生一个布尔结果;statement指用分号结尾的简单语句或者封闭在花括号内的一组简单语句即复合语句。
【例2-19】对给定的两个数按照升序显示。
publicclassSortTwo{
publicstaticvoidmain(String[]args){
intx=23,y=11;
if(x>y){
//借助变量z,x与y互换位置使其有序intz=x;
x=y;
y=z;
}
System.out.println("Thenumberinsortedorderare:"+x+""+y);
}
}
程序运行结果如图2-27所示。图2-27SortTwo.java的执行结果在这个程序中,当条件表达式(x>y)的值为true时,执行了一条复合语句。复合语句完成了x和y的互换。初学者在这里容易犯一个错误,会写成下面的形式:
if(x>y)
//借助变量z,x与y互换位置使其有序
intz=x;
x=y;
y=z;
System.out.println("Thenumberinsortedorderare:"+x+""+y);缺少了{},系统会认为,当条件表达式(x>y)的值为true时,执行一条语句“intz=x;”,而其他部分被看做是if语句执行完后要顺次执行的语句,与if条件成立时的执行行为无关。因此在编写程序时,一定要注意执行语句的完整性,恰当地使用{}。
同时在编写程序的时候要注意缩进和括号的位置。将与if语句关联的Action语句缩进,可以给读者一个提示:Action语句的执行依赖if语句表达式。一致的缩进有助于提高程序的可读性,多数程序员通常每层缩进三到四个空格。所以if语句要写成下面的形式:
if(x>y){//if语句首行:包含了{,以节省行空间
intz=x;//比首行缩进了四个空格
x=y;
y=z;
}
//结束括号放在单独行,缩进层次与相关的if语句相同,直观地表
//示程序中随后的语句与该if语句是不相关的
【例2-20】对给定的两个数,求出最大值并显示。
publicclassMaximum{
publicstaticvoidmain(String[]args){
intx=35,y=11;
intmaximum;
if(x>y){ //x大吗
maximum=x; //x大:maximum得到x的值}
else{ //x<=y吗
maximum=y; //x<=y:maximum得到y的值
}
System.out.println("Themaximumof"+x+"and"+y+"is:"+maximum);
}
}
程序运行结果如图2-28所示。图2-28Maximum.java的执行结果在这个程序中,有以下几点说明:
(1) if和else具有相同的缩进层次,直观地表明它们是一个整体。
(2)某个条件满足时要执行语句体,一定要用{}括起来。当只有一条执行语句时,可以省略{}。本程序没有省略,以使表达更清晰,建议初学者这样做。
(3) if分句和else分句之间不能有任何“非法”语句出现,否则破坏了if-else的完整性,编译系统会给出错误提示。如下面的语句:
if(value2==value1){
System.out.println(“Theyareequal!);
}
temp=value1;//“割断”了if和els
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 读书的体会作文400字
- 仪器、设备维修申请单范本
- 大学的学习计划15篇
- 2023四年级语文下册 第3单元 9 短诗三首配套教学实录 新人教版
- 代理成本-详解
- 2024-2025学年高中政治 专题4 4 坚持和完善人民代表大会制度教学实录 新人教版选修3
- 趣味篮球活动方案9篇
- 公司的承诺书合集七篇
- 2024年版民办幼儿园经营管理承包合同版B版
- 前台年度工作总结5篇
- CX-TGK01C型微电脑时间温度控制开关使用说明书
- CDR-临床痴呆评定量表
- 《八年级下学期语文教学个人工作总结》
- 电仪工段工段长职位说明书
- 恒亚水泥厂电工基础试题
- 简易送货单EXCEL打印模板
- 4s店信息员岗位工作职责
- 旋转导向+地质导向+水平井工具仪器介绍
- 无心磨的导轮及心高调整讲解
- 乳腺癌化疗的不良反应级处理ppt课件
- 艾灸疗法(课堂PPT)
评论
0/150
提交评论