3.4 运算符
运算符是一些特殊的符号,主要用于数学函数、一些类型的赋值语句和逻辑比较方面。Java中提供了丰富的运算符,如赋值运算符、算术运算符、比较运算符等。本节将向读者介绍这些运算符。
3.4.1 赋值运算符
赋值运算符以符号“=”表示,它是一个二元运算符(对两个操作数做处理),其功能是将右方操作数所含的值赋给左方的操作数。例如:
int a = 100;
该表达式是将100赋值给变量a。左方的操作数必须是一个变量,而右边的操作数则可以是任何表达式,包括变量(如a、number)、常量(如123、'book')、有效的表达式(如45 * 12)。
由于赋值运算符“=”处理时会先取得右方表达式处理后的结果,因此一个表达式中若含有两个以上的“=”运算符,会从最右方的“=”开始处理。
【例3.7】使用赋值运算符同时为两个变量赋值(实例位置:资源包\TM\sl\3\7)
在项目中创建类Eval,在主方法中定义变量,使用赋值运算符为变量赋值。
运行结果如下:
c值为:19 b值为:19
说明
在Java中可以把赋值运算符连在一起使用。如:
x = y = z = 5;
在这个语句中,变量x、y、z都得到同样的值5,但在实际开发中建议开发者分开对其进行赋值,这样可以让代码的层次更清晰。
3.4.2 算术运算符
Java中的算术运算符主要有+(加)、-(减)、*(乘)、/(除)、%(求余),它们都是二元运算符。Java中算术运算符的功能及使用方式如表3.5所示。
表3.5 Java算术运算符
其中,“+”和“-”运算符还可以作为数值的正负符号,如+5、-7。
注意
在进行除法运算时,0不能做除数。例如,对于语句“int a = 5 / 0;”,系统会抛出ArithmeticException异常。
下面通过一个小程序来介绍算术运算符的使用方法。
【例3.8】使用算术运算符模拟计算器(实例位置:资源包\TM\sl\3\8)
创建ArithmeticOperator类,让用户输入两个数字,分别用5种运算符对这两个数字进行计算。
运行结果如图3.6所示,图中数字23和15为用户在控制台中输入的值。
图3.6 运行结果
说明
代码中出现的Scanner扫描器类可以让程序获得用户在控制台输入的值,关于Scanner类的详细用法请参考本书“第11章常用类库”的相关内容。
3.4.3 自增和自减运算符
自增、自减运算符是单目运算符,可以放在操作元之前,也可以放在操作元之后。操作元必须是一个整型或浮点型变量。自增、自减运算符的作用是使变量的值增1或减1。放在操作元前面的自增、自减运算符,会先将变量的值加1(减1),然后使该变量参与表达式的运算。放在操作元后面的自增、自减运算符,会先使变量参与表达式的运算,然后将该变量加1(减1)。例如:
++a(--a) //表示在使用变量a之前,先将a的值加(减)1 a++(a--) //表示在使用变量a之后,将a的值加(减)1
粗略地分析,“++a”与“a++”的作用都相当于a = a + 1。假设a = 4,则:
b = ++a; //先将a的值加1,然后赋给b,此时a值为5,b值为5
再看另一个语法,同样假设a = 4,则:
b = a++; //先将a的值赋给b,再将a的值变为5,此时a值为5,b值为4
3.4.4 比较运算符
比较运算符属于二元运算符,用于程序中的变量之间、变量和自变量之间以及其他类型的信息之间的比较。比较运算符的运算结果是boolean型。当运算符对应的关系成立时,运算结果为true,否则为false。所有比较运算符通常作为判断的依据用在条件语句中。比较运算符共有6个,如表3.6所示。
表3.6 比较运算符
【例3.9】使用不同的比较运算符判断两个整数的关系(实例位置:资源包\TM\sl\3\9)
在项目中创建类Compare,在主方法中创建整型变量,使用比较运算符对变量进行比较运算,并输出运算后的结果。
运行结果如下:
number1>number2的返回值为:false number1< number2返回值为:true number1==number2返回值为:false number1!=number2返回值为:true number1>= number2返回值为:false number1<=number2返回值为:true
3.4.5 逻辑运算符
返回类型为布尔型的表达式(如比较运算符)可以被组合在一起构成一个更复杂的表达式。这是通过逻辑运算符来实现的。逻辑运算符包括&(&&)(逻辑与)、||(逻辑或)、!(逻辑非)。逻辑运算符的操作元必须是boolean型数据。在逻辑运算符中,除了“!”是一元运算符,其他都是二元运算符。表3.7给出了逻辑运算符的用法和含义。
表3.7 逻辑运算符
结果为boolean型的变量或表达式可以通过逻辑运算符组合为逻辑表达式。
用逻辑运算符进行逻辑运算时,结果如表3.8所示。
表3.8 使用逻辑运算符进行逻辑运算
逻辑运算符“&&”与“&”都表示“逻辑与”,那么它们之间的区别在哪里呢?从表3.8中可以看出,当两个表达式都为true时,“逻辑与”的结果才会是true。使用逻辑运算符“&”会判断两个表达式;而逻辑运算符“&&”则是针对boolean类型的类进行判断的,当第一个表达式为false时则不去判断第二个表达式,直接输出结果,从而节省计算机判断的次数。通常将这种在逻辑表达式中从左端的表达式可推断出整个表达式的值的情况称为“短路”,而将那些始终需要执行逻辑运算符两边的表达式才能推断出整个表达式的值的情况称为“非短路”。“&&”属于“短路”运算符,而“&”属于“非短路”运算符。
【例3.10】使用不同的比较运算符判断两个整数的关系(实例位置:资源包\TM\sl\3\10)
在项目中创建类Calculation,在主方法中创建3个整数,分别记录男生人数、女生人数和总人数,使用逻辑运算符来判断“男生人数大于女生人数并且总人数大于30人”和“男生人数大于女生人数或者总人数大于30人”这两种情况是否存在。
运行结果如下:
男生人数大于女生人数并且总人数大于30人:false 男生人数大于女生人数或者总人数大于30人:true
3.4.6 位运算符
位运算符除“按位与”和“按位或”运算符外,其他只能用于处理整数的操作数,包括byte、short、char、int和long等数据类型。位运算是完全针对位方面的操作。整型数据在内存中以二进制的形式进行表示,如int型变量7的二进制表示是00000000 00000000 00000000 00000111。
左边最高位是符号位,最高位是0表示正数,若为1则表示负数。负数采用补码表示,如-8的二进制表示为111111111 111111111 1111111 11111000。这样就可以对整型数据进行按位运算。
图3.7 5 & -4的运算过程
1.“按位与”运算
“按位与”运算的运算符为“&”,为双目运算符。“按位与”运算的运算法则是:如果两个整型数据a、b对应位都是1,则结果位才是1,否则为0。如果两个操作数的精度不同,则结果的精度与精度高的操作数相同,如图3.7所示。
2.“按位或”运算
“按位或”运算的运算符为“|”,为双目运算符。“按位或”运算的运算法则是:如果两个操作数对应位都是0,则结果位才是0,否则为1。如果两个操作数的精度不同,则结果的精度与精度高的操作数相同,如图3.8所示。
3.“按位取反”运算
“按位取反”运算也称“按位非”运算,运算符为“~”,为单目运算符。“按位取反”就是将操作数二进制中的1修改为0,0修改为1,如图3.9所示。
4.“按位异或”运算
“按位异或”运算的运算符是“^”,为双目运算符。“按位异或”运算的运算法则是:当两个操作数的二进制表示相同(同时为0或同时为1)时,结果为0,否则为1。若两个操作数的精度不同,则结果的精度与精度高的操作数相同,如图3.10所示。
图3.8 3 | 6的运算过程
图3.9 ~7的运算过程
图3.10 10 ^ 3的运算过程
5.移位操作
除了上述运算符,还可以对数据按二进制位进行移位操作。Java中的移位运算符有以下3种:
<<:左移。
>>:右移。
>>>:无符号右移。
左移就是将运算符左边的操作数的二进制数据,按照运算符右边操作数指定的位数向左移动,右边移空的部分补0。右移则复杂一些。当使用“>>”符号时:如果最高位是0,右移空的位就填入0;如果最高位是1,右移空的位就填入1,如图3.11所示。
Java还提供了无符号右移“>>>”,无论最高位是0还是1,左侧被移空的高位都填入0。
图3.11 右移
技巧
移位可以实现整数除以或乘以2n的效果。例如,y << 2与y*4的结果相同,y >> 1的结果与y / 2的结果相同。总之:一个数左移n位,就是将这个数乘以2n;一个数右移n位,就是将这个数除以2n。
3.4.7 复合赋值运算符
和其他主流编程语言一样,Java中提供了复合赋值运算符。所谓复合赋值运算符,就是将赋值运算符与其他运算符合并成一个运算符来使用,从而同时实现两种运算符的效果。Java中的复合运算符如表3.9所示。
表3.9 复合赋值运算符
以“+=”为例,虽然“a += 1”与“a = a + 1”二者最后的计算结果是相同的,但是在不同的场景下,两种运算符都有各自的优势和劣势:
(1)低精度类型自增。
在Java编译环境中,整数的默认类型是int型,因此下面的赋值语句会报错:
byte a = 1; //创建byte型变量a a = a + 1; //让a的值+1,错误提示:无法将int型转换成byte型
在没有进行强制转换的条件下,a+1的结果是一个int值,无法直接赋给一个byte变量。但是如果使用“+=”实现递增计算,就不会出现这个问题。
byte a = 1; //创建byte型变量a a += 1; //让a的值+1
(2)不规则的多值相加。
“+=”虽然简洁、强大,但是有些时候是不好用的,比如下面这个语句:
a = (2 + 3 - 4) * 92 / 6;
这条语句如果改成使用复合赋值运算符,代码就会显得比较烦琐,代码如下:
a += 2; a += 3; a -= 4; a *= 92; a /= 6;
3.4.8 三元运算符
三元运算符的使用格式如下:
条件式 ? 值1 : 值2
三元运算符的运算法则是:若条件式的值为true,则整个表达式取值1,否则取值2。例如:
上述程序表达式“20 < 45”的运算结果返回真,那么boolean型变量b取值为true。相反,如果表达式的运算结果返回为假,则boolean型变量b取值为false。
三元运算符等价于if…else语句,例如上述代码等价于:
3.4.9 运算符的优先级
Java中的表达式就是使用运算符连接起来的符合Java规则的式子。运算符的优先级决定了表达式中运算执行的先后顺序。通常,优先级由高到低的顺序依次是:
增量和减量运算。
算术运算。
比较运算。
逻辑运算。
赋值运算。
如果两个运算有相同的优先级,那么左边的表达式要比右边的表达式先被处理。表3.10显示了在Java中众多运算符特定的优先级。
表3.10 运算符的优先级
技巧
在编写程序时尽量使用圆括号来指定运算次序,以免产生错误的运算顺序。
编程训练(答案位置:资源包\TM\sl\3\编程训练)
【训练5】计算机车加速度 平均加速度,即速度的变化量除以这个变化所用的时间。现有一辆轿车用了8.7秒从每小时0千米加速到每小时100千米,计算并输出这辆轿车的平均加速度。
【训练6】求解二元一次方程组 使用克莱姆法则求解二元一次方程组。
提示:克莱姆法则求解二元一次方程组的公式如下: