在程序设计中经常要进行各种运算,从而达到改变变量值的目的。要实现运算,就要使用运算符。运算符是用来表示某一种运算的符号,它指明了对操作数所进行的运算。按操作数的数目来分,有一元运算符(如++)、二元运算符(如+、>)和三元运算符(如?:),它们分别对应于一个、两个和三个操作数。按照运算符功能来分,基本的运算符有下面几类。
顾名思义,算术运算符就是用来进行算术运算的符号。这类运算符是最基本、最常见的。算术运算符作用于整型或浮点型数据,完成相应的算术运算。Java语言的算术运算符分为一元运算符和二元运算符。一元运算符只有一个操作数参加运算,而二元运算符则有两个操作数参加运算。
二元算术运算符如表3.8所示。
表3.8 二元算术运算符
对于除号“/”,它的整数除法和实数除法是有区别的:两个整数之间做除法时,只保留整数部分而舍弃小数部分。对于两个整数之间的除法和取模运算,式子(a/b)*b+(a%b)==a恒成立。
对取模运算符“%”来说,其操作数可以为浮点数。即a%b与a-((int)(a/b)*b)的语义相同,这表示a%b的结果是除完后剩下的浮点数部分。只有单精度操作数的浮点表达式按照单精度运算求值,产生单精度结果。如果浮点表达式中含有一个或一个以上的双精度操作数,则按双精度运算,结果是双精度浮点数,如37.2%10=7.2。
值得注意的是Java语言对加运算符进行了扩展,使它能够进行字符串的连接,如"abc"+"de",得到字符串"abcde",详见3.7.7节。
一元算术运算符如表3.9所示。
表3.9 一元算术运算符
加1、减1运算符既可放在操作数之前(如++i或——i),也可放在操作数之后(如i++或i——),但两者的运算方式不同。如果放在操作数之前,操作数先进行加1或减1运算,然后将结果用于表达式的操作;如果放在操作数之后,则操作数先参加其他的运算,然后再进行加1或减1运算。例如:
说明: 一元运算符与操作数之间不允许有空格。加1或减l运算符不能用于表达式,只能用于简单变量。例如,++(x+1)有语法错误。
关系运算符用于比较两个值之间的大小,结果返回逻辑型的值true或false。关系运算符都是二元运算符,如表3.10所示。
表3.10 关系运算符
注意: 不能在浮点数之间做“==”的比较,因为浮点数在表达上有难以避免的微小误差,精确的相等比较无法达到,所以这类比较没有意义。
逻辑运算与关系运算的关系非常密切,关系运算是运算结果为逻辑型量的运算,而逻辑运算是操作数与运算结果都是逻辑型量的运算。逻辑运算符如表3.11所示。
表3.11 逻辑运算符
!为一元运算符,实现逻辑非。&、|为二元运算符,实现逻辑与、逻辑或运算。简洁运算(&&、||)与非简洁运算(&、|)的区别在于:非简洁运算在必须计算完左右两个表达式之后,才取结果值;而简洁运算可能只需计算左边的表达式而不用计算右边的表达式,即对于&&,只要左边表达式为false,就不用计算右边表达式,则整个表达式为false;对于||,只要左边表达式为true,就不用计算右边表达式,则整个表达式为true。
对于异或运算可以通过一句话来记住它:两个值不同,值为真;两个值相同,值为假(不同,称为“异”,也就是说两个值不能相同)。
下面的例子说明了关系运算符和逻辑运算符的使用。
【例3.8】 关系运算符和逻辑运算符的使用。
其运行结果为:
a<b=false x^y=true a%e=1 f=0
该程序第12行的条件中左边式子b<0虽然为false,但非简洁运算符“&”还必须要求再计算右边的式子e!=0是否成立,尽管该式成立,但整个式子“b<0&e!=0”的结果值仍为false,因此该行后面的输出语句中的“b/0”永远都不会被计算;但第15行if语句中的“&&”为简洁运算符,所以只要左边的式子“f!=0”不成立,就不需计算右边的“a/f>5”式子,所以在运行时不会发生除0溢出的错误。
位运算符是对操作数以二进制比特位为单位进行的操作和运算,Java语言中提供了如表3.12所示的位运算符。
表3.12 位运算符
Java语言的位运算符可分为按位运算和移位运算两类。这两类位运算符中,除一元运算符“~”以外,其余均为二元运算符。位运算符的操作数只能为整型或字符型数据。有的符号(如&,|, ^ )与逻辑运算符的写法相同,但逻辑运算符的操作数为boolean型的量。用户在使用这种运算符要注意它们的区别。
关于赋值运算符“=”,我们在3.4节介绍变量的赋值时已经简单提过。简单的赋值运算是把一个表达式的值直接赋给一个变量或对象,使用的赋值运算符是“=”,其格式如下:
变量或对象=表达式;
在赋值运算符两侧的类型不一致的情况下,则需要按3.5节中介绍的规则进行自动或强制类型转换。即变量从占用内存较少的短数据类型转化成占用内存较多的长数据类型时,Java会自动进行隐含类型转换;而将变量从较长的数据类型转换成较短的数据类型时,则必须做强制类型转换,即采用“(类型)表达式”的方式。
赋值运算符右端的表达式可以还是赋值表达式,形成连续赋值的情况。例如:
a=b=c=8;
首先执行c=8,该赋值表达式的值是8,然后再执行b=8,该表达式的值是8,最后执行a=8。
在赋值符“=”前加上其他运算符,即构成扩展赋值运算符,例如,a+=3等价于a=a+3。即扩展赋值运算符是先进行某种运算之后,再对运算的结果进行赋值。表3.13列出了Java语言中的扩展赋值运算符及等效表达式。
表3.13 扩展赋值运算符及等效表达式
Java语言提供了高效简便的三元条件运算符(?:)。该运算符的格式如下:
表达式1?表达式2:表达式3;
其中,“表达式1”是一个结果为布尔值的逻辑表达式。该运算符的功能是:计算“表达式1”的值,当“表达式1”的值为true时,则将“表达式2”的值作为整个表达式的值;当“表达式1”的值为false时,则将“表达式3”的值作为整个表达式的值。例如,
当要通过测试某个表达式的值来选择两个表达式中的一个进行计算时,用条件运算符来实现是一种简练的方法。这时,它实现了if-else语句的功能。
字符串运算符“+”是以String为对象进行的操作。运算符“+”完成字符串连接操作,如果必要,系统则自动把操作数转换为String型。例如:
如果操作数是一个对象,则可利用相应类中的toString()方法,将该对象转换成字符串,然后再进行字符串连接运算。“+=”运算符也可以用于字符串。如设s1为String型,a为int型,则有
表达式是由变量、常量、对象、方法调用和操作符组成的式子,它执行这些元素指定的计算并返回某个值。如,a+b,c+d等都是表达式,表达式用于计算并对变量赋值,或作为程序控制的条件。作为特例,单独的常量、变量或方法等均可看作是一个表达式。
在对一个表达式进行运算时,要按运算符的优先顺序从高向低进行。运算符的优先级决定了表达式中不同运算执行的先后顺序,大体上来说,从高到低是:一元运算符、算术运算、关系运算和逻辑运算、赋值运算。运算符除有优先级外,还有结合性,运算符的结合性决定了并列的多个同级运算符的先后执行顺序。同级的运算符大都是按从左到右的方向进行(称为“左结合性”)。大部分运算的结合性都是从左向右,而赋值运算、一元运算等则有右结合性。表3.14给出了Java语言中运算符的优先级和结合性。
表3.14 运算符的优先级及结合性(表顶部的优先级较高)
在表达式中,可以用括号()显式地标明运算次序,括号中的表达式首先被计算。适当地使用括号可以使表达式的结构清晰。例如:
a>=b&&c<d||e==f
可以用括号显式地写成:
((a<=b)&&(c<d))||(e==f)
这样就清楚地表明了运算次序,使程序的可读性加强。
注意: 括号的使用必须匹配。