陆——运算符、表达式与语句
一、运算符
程序是由许多语句( statement )组成的,而语句组成的基本单位就是表达式与运算符。Java 的运算符可分为 4 类:算术运算符、关系运算符、逻辑运算符和位运算符。
Java 中的语句有多种形式,表达式就是其中的一种形式。表达式是由操作数与运算符所组成的。操作数可以是常量、变量,也可以是方法,而运算符就是数学中的的运算符号,如 “ + ”、“ - ”、“ * ”、“ / ”、“ % ” 等。
例如:
A + B = 100;
其中,A 与 B 都是操作数,而 “ + ” 就是运算符,它们合起来就是一个表达式。
1.赋值运算符
若为各种不同类型的变量赋值,就需要用到赋值运算符(Assignment Operator)。简单的赋值运算符由等号( = )实现,只是把等号右边的值赋予等号左边的变量。
例如:
int num_a = num_b + 10;
这句话的含义是,把变量 num_b 的值加 10,再赋( = )给 num_a。
2.一元运算符
对于很多表达式而言,运算符前后都会有操作数。但有一类操作符比较特别,它只需要一个操作数。这类运算符称为一元运算符(或单目运算符,Unary Operator)。
下表为一元运算符的成员:
一元运算符 | 意义 |
+ | 正号 |
- | 负号 |
! | NOT,非 |
~ | 取补码 |
++ | 变量值自增1 |
-- | 变量值自减1 |
举例说明这些符号的含义:
+5; | //表示正数5 |
~x; | //表示取变量 x 的补码 |
y = -x; | //表示负 x 的值赋给变量 y |
!x; | //x 的 NOT 运算,若 x 为 true,则 !x 返回 false。若 x 为 false,则 !x 返回 true |
x = ~x | //表示将 x 的值取反,并赋给自己 |
3.算术运算符
算术运算符(Arithmetic Operator)用于量之间的运算。
算术运算符在数学上经常会用到,下表将列出它的成员:
算术运算符 | 意义 |
+ | 加法 |
- | 减法 |
* | 乘法 |
/ | 除法 |
% | 余数 |
(1)加法运算符 “ + ”
将加法运算符 “ + ” 的前后两个操作数相加。
(2)减法运算符 “ - ”
将减法运算符 “ - ” 前面的操作数减去后面的操作数。
(3)乘法运算符 “ * ”
将乘法运算符 “ * ” 前后两个操作数相乘。
(4)除法运算符 “ / ”
将除法运算符 “ / ” 前面的操作数除以后面的操作数。
使用除法运算符时,要特别注意数据类型的问题。若被除数和除数都是整型,且被除数不能被除数整除时,这时输出的结果为整数(即整型数/整型数 = 整型数)。这是因为整型变量无法保存小数点后面的数据所致,因此在声明数据类型及输出时要按照相对应的数据类型来声明。
如若为了保证程序运行结果与实际的值相同,可以使用强制性的类型转换。
(5)取余运算符 “ % ”
将取余运算符 “ % ” 前面的操作数除以后面的操作数,取其得到的余数。
Java中的取余操作数也可以是负数和浮点数,而在 C/C++ 中,取余运算的操作数只能是整数。
4.逻辑运算符
逻辑运算符只对布尔型操作数进行运算并返回一个布尔型数据。也就是说,逻辑运算符的操作数和运行结果只能是真( true )或者( false )。
常见的逻辑运算符有 3 个,即与( && )、或( || )、非( !),如下表所示:
运算符 | 含义 | 解释 |
&& | 与(AND) | 两个操作数皆为真,运算结果才为真 |
& | ||
|| | 或(OR) | 两个操作数只要一个为真,运算结果就为真 |
| | ||
! | 非(NOT) | 返回与操作数相反的布尔值 |
在逻辑运算中,“ && ” 和 “ || ” 属于所谓的短路逻辑运算符(Short-Circuit Logical Operators)。对于逻辑运算符 “ && ”,要求左右两个表达式都为 true 时才返回 true,如果左边第一个表达式为 false 时,它立刻就返回 false,就好像短路了一样立刻返回,省去了一些不必要的计算开销。
类似的,对于逻辑运算符 “ || ”,要求左右两个表达式有一个为 true 时就返回 true,如果左边第一个表达式为 true 时,它立刻就返回 true。
有时,我们需要逻辑 “ 与 ” 操作和 “ 或 ” 操作的两个操作数均需要运算,这时就需要使用避免短路的逻辑运算符—— “ & ” 和 “ | ”,它们分别是可短路的逻辑运算符(&& 和 || )一半的字符。
5.位运算符
位操作是指对操作数以二进制位(bit)为单位进行的运算。其运算的结果为整数。位操作的第一步是把操作数转换为二进制的形式,然后按位进行布尔运算,运算的结果也为二进制数。位操作运算符(bitwise operators)有 7 个。如下表:
位运算符 | 含义 |
& | 按位与(AND) |
| | 按位或(OR) |
^ | 按位异或(XOR) |
~ | 按位取反(NOT) |
<< | 左移位(Signed left shift) |
>> | 带符号右移位(Signed right shift) |
>>> | 无符号右移位(Unsigned right shift) |
现用图例解释上述运算符:
(1)与( & ):两个二进制位均为 1,结果为 1,否则为 0。
0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 |
0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |
0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
(2)或( | ):两个二进制位均为 0,结果为 0,否则为 1。
0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 |
0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |
0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 |
(3)异或( ^ ):两个二进制位不同,结果为 1,相同则为 0。
0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 |
0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |
0 | 0 | 0 | 0 | 1 | 1 | 0 | 1 |
(4)取反( ~ ):结果与原来二进制位相反:1 变 0 , 0 变 1。
0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |
1 | 1 | 1 | 1 | 0 | 1 | 0 | 0 |
(5)有符号右移( >> ):高位负数补 1,正数补 0 ,低位抛弃。如:-11 >> 2 = -3。
1 | 1 | 1 | 1 | 0 | 1 | 0 | 1 |
1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 |
(6)左移( << ):高位抛弃,低位补零。如:11 << 2 = 44。
0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 |
0 | 0 | 1 | 0 | 1 | 1 | 0 | 0 |
(7)无符号右移( >>> ):低位抛弃,高位补零。如:139 >>> 2 = 34。
1 | 0 | 0 | 0 | 1 | 0 | 1 | 1 |
0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 |
6.三元运算符
三元(Ternary)运算符也称三目运算符,它的运算符是“?:”,有三个操作数。
操作流程如下:首先判断条件,如果条件满足,就会赋予一个变量一个指定的内容(冒号:在此之前),不满足会赋予变量另外的一个内容(冒号之后的),其操作语法如下:
数据类型 变量 = 布尔表达式 ?条件满足设置内容 :条件不满足设置内容;
例:
int sum = x > y ? x : y;
其含义是:
如果 x 的内容大于 y,则将 x 的内容赋值给 sum,否则将 y 的值赋值给 sum。
本质上来讲,三元运算符是简写的 if-else语句。以上举例完全可以利用 if-else 代替。
7.关系运算符与 if 语句
if 语句通常用于某个条件进行真(true)、假(false)识别。if 语句的格式如下。
if(判断条件){
语句;
}
如果括号中的判断条件成立,就会执行后面的语句;若是判断条件不成立,则后面的语句就不会被执行。
其下列出关系运算符的成员:
关系运算符 | 意义 |
> | 大于 |
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
== | 等于 |
!= | 不等于 |
在 Java 中,关系运算符的表示方式和在数学中类似,但是由于赋值运算符为“ = ”,为了避免混淆,当使用关系运算符“等于”时,就必须用 2 个等号( == )表示;而关系运算符“不等于”的形式有些特别,用“ != ”代表,这是因为想要从键盘上取得数学上的不等于符号“≠”较为困难,同时 “ ! ” 有 “ 非 ” 的意思,所以就用“ != ” 表示不等于。
当使用关系运算符(Relational Operator)去判断一个表达式的成立与否时,若是判断式成立则会产生一个响应值 true,若是判断式不成立,则会产生响应值 false。
8.递增与递减运算符
递增与递减运算符在C/C++中就已经存在了,Java 中将他们保留了下来,这是因为它们具有相当大的便利性。
下表列出递增与递减运算符的成员:
递增与递减运算符 | 意义 |
++ | 递增,变量值加1 |
-- | 递减,变量值减1 |
9.括号运算符
括号( )也是 Java 的运算符,如下表:
括号运算符 | 意义 |
( ) | 提高括号中表达式的优先级 |
括号运算符( )是用来处理表达式的优先级的,与数学上使用相同。
10.运算符的优先级
下表将列出各个运算符的优先级排列,数字越小的表示优先级越高(优先级排名靠前)。
优先级 | 运算符 | 类 | 结合性 |
1 | () | 括号运算符 | 由左至右 |
1 | [] | 方括号运算符 | 由左至右 |
2 | 1、+(正号)、-(负号) | 一元运算符 | 由右至左 |
2 | ~ | 位逻辑运算符 | 由右至左 |
2 | ++、-- | 递增与递减运算符 | 由右至左 |
3 | *、/、% | 算术运算符 | 由左至右 |
4 | +、- | 算术运算符 | 由左至右 |
5 | <<、>> | 位左移、右移运算符 | 由左至右 |
6 | >、>=、<、<= | 关系运算符 | 由左至右 |
7 | ==、!= | 关系运算符 | 由左至右 |
8 | &(位运算符 AND) | 位逻辑运算符 | 由左至右 |
9 | ^(位运算符号 XOR) | 位逻辑运算符 | 由左至右 |
10 | |(位运算符号 OR) | 位逻辑运算符 | 由左至右 |
11 | && | 逻辑运算符 | 由左至右 |
12 | || | 逻辑运算符 | 由左至右 |
13 | ?: | 条件运算符 | 由右至左 |
14 | = | 赋值运算符 | 由右至左 |
上表的最后一栏是运算符的结合性(associativity)。
什么是结合性?
结合性就是可以让程序设计者了解到运算符与操作数之间的关系及其相对位置。举例来说,当使用同一优先级的运算符时,结合性就非常重要了,它决定社会先被处理。
二、表达式
表达式是由常量、变量或是其他操作数与运算符所组合而成的语句。
例:
a + 3 //表达式由变量 a、算术运算符与常量 3 组成
此外,Java 还有一些相当简洁的写法,是将算术运算符和赋值运算符结合成为新的运算符。
下表将列出这些运算符:
运算符 | 范例用法 | 说明 | 意义 |
+= | a += b | a + b 的值存放到 a 中 | a = a + b |
-= | a -= b | a - b 的值存放到 a 中 | a = a - b |
*= | a *= b | a * b 的值存放到 a 中 | a = a * b |
/= | a /= b | a / b 的值存放到 a 中 | a = a / b |
%= | a %= b | a % b 的值存放到 a 中 | a = a % b |
例:
a++ //相当于 a = a + 1
a-=5 //相当于 a = a - 5
这种写法可以减少程序的行数,提高运行的速度。在优秀程序设计里有个著名的 KISS(Keep It Simple and Stupid)原则,即让代码保持简单,这里 Stupid 不是愚蠢的意思,而是表示一目了然。一目了然的代码易于理解和维护。
1.算术表达式
算术表达式用于数值计算。它是由算术运算符和变量或常量组成,其结果是一个数值。
例:
int a = 123456789,b = 9;
System.out.println("a * b = " + a * b);
2.关系表达式
关系表达式常用于程序判断语句中,由关系运算符组成,其运算结果为逻辑型数值。
例:
int a = 5,b = 4;
boolean t1 = a > b;
boolean t2 = a == b;
System.out.println("a > b : " + t1);
System.out.println("a == b : " + t2);
3.逻辑表达式
用逻辑运算符将关系表达式或逻辑量连接起来的有意义的式子称为逻辑表达式。
逻辑表达式的值也是一个逻辑值,即 “ true ” 或 “ false ”。
例:
boolean t = (1 + 1 == 2) && (1 + 2 == 3);
System.out.println((1 + 1 == 2) && (1 + 2 == 3):" + t);
4.赋值表达式
赋值表达式由赋值运算符和操作数组成,赋值运算符用于给变量赋值。
例:
int x = 123;
int y = 6;
int z;
z = x * y - 700;
System.out.println("x * y - 700 = " + z);
赋值表达式的功能是先计算右侧表达式的值,再赋予左边的变量。赋值运算符具有右结合性。
5.表达式的类型转换
Java 是一个很有弹性的程序设计语言,当上述情况发生时,只要坚持 “以不流失数据为前提”的大原则,即可进行不同的类型转换,使不同类型的数据、表达式都能继续存储。规则如下:
(1)占用字节较少的数据类型转换成占用字节较多的数据类型。
(2)字符类型会转换成 int 类型。
(3)int 类型会转换成 float 类型。
(4)表达式中若某个操作数的类型为 double ,则另一个操作数也会转换成 double 类型。
(5)布尔类型不能转换成其他类型。
三、语句
表达式由运算符和操作数组成,语句(statement)则由表达式组成。例如 a + b 是一个表达式,加上分号后就成为了 a + b;
这就是一个语句。计算机执行程序就是由若干条语句进行的。每个语句后用分号( ;)隔开。多个语句只要用分号隔开,可以处于同一行。
1.语句中的空格
在 Java 程序语句中,空格是必不可少的。一方面,所有的语言指令都需要借助空格来分割标注。
如:
int a; //变量类型( int )和变量( a )之间需要空格隔开
另一方面,虽然 Java 编译器在编译的过程中,会把所有非必须得空格过滤掉,但空格可以使程序更具有可读性,更加美观。
2.空语句
Java 中有一种语句什么也不执行,这就是空语句。空语句是由一个分号( ;)组成的语句。
空语句是什么也不执行的语句。在程序中空语句常常用来作空循环体。
空语句还可以用于在调试时留空以待以后添加新的功能。如果不是出于这种目的,一般不建议使用空语句,因为空语句不完成任何功能,但同样会额外占用计算机资源。
提示:因为空语句由( ;)组成,所以如果认为一条语句后有两个( ;)是不合法的,但是由于 Java 程序语句可以处于同一行,所以即使一条语句后有几个( ;)都是合法的。
3.声明语句
声明语句格式如下:
<声明数据类型> <变量1> … <变量n>;
使用声明语句可以在每一条语句中声明一个变量,也可以在一条语句中声明多个变量。还可以在声明变量的同时,直接与赋值语句连用为变量赋值。
如果对声明的成员变量没有赋值,那么将赋为默认的值。默认初始值:整型为0;布尔类型变量默认值为 false;引用数据类型和字符串类型默认都为 null。
4.赋值语句
除了可以在声明语句中为变量赋初值外,还可以在程序中为变量重新复制,者就用到了赋值语句。
例如:
pi = 3.14;
r = 25;
s = pi * r * r;
在程序代码中,使用赋值语句给变量赋值,赋值符号右边可以是一个常量或变量,也可以是一个表达式。程序在运行时先计算表达式的值,然后将结果赋给等号左边的变量。
四、本文注意事项
1. & 和 &&、|、|| 的关系
对于“ 与 ”操作:有一个条件不满足,结果就是 false ;普通与( & ):所有的判断条件都要执行;短路与( && ):如果前面有条件已经返回了 false,不再向后判断,那么最终结果就是 false。
对于“ 或 ”操作:有一个条件满足,结果就是 true。对于普通或( | ):所有的判断条件都要执行;短路或( || ):如果前面有条件返回了 true,不再向后判断,那么最终结果就是 true。
2.递增与递减运算符
递增与递减运算符通常单独使用,不与其他操作符一起组成语句。
3.位运算的技巧
任何数与 0000 0001(二进制)进行或( | )运算后,第一位将变为 1,与 1111 1110(二进制)进行与( & )运算后,第一位将变为 0。
位运算通常用于设置或获取标志位,及判断相应的操作是否成功。