
3.1 运算符

在Java 中,与类无关的运算符主要有赋值运算符、算术运算符、关系运算符、逻辑运算符和位运算符,下面介绍各种运算符的使用方法。
3.1.1 赋值运算符
赋值运算符的符号为 “=”,它的作用是将数据、变量或对象赋值给相应类型的变量或对象,例如:

赋值运算符的结合性为从右到左。例如,在下面的代码中,首先计算表达式 “9412 + 75”,然后将计算结果赋值给变量result:

如果两个变量的值相同,也可以使用如下代码完成赋值操作:

3.1.2 算术运算符
算术运算符支接整数类型数据和浮点类型数据的运算。当整数类型数据与浮点类型数据之间进行算术运算时,Java 会自动完成数据类型的转换,并且计算结果为浮点类型。Java 中算术运算符的功能及使用方法如表3.1 所示。
表3.1 算术运算符的功能及使用方法

在进行算术运算时,有两种情况需要考虑:一种情况是没有小数参与运算;另一种情况则是有小数参与运算。
1.没有小数参与运算
在对整数类型数据或变量进行加法(+)、减法(-)和乘法(*)运算时,与数学中的运算方式完全相同,这里就不再介绍了。下面介绍在整数之间进行除法(/)和求余(%)运算时需要注意的问题。
(1)进行除法运算时需要注意的问题。
当在整数类型数据和变量之间进行除法运算时,无论能否整除,运算结果都将是一个整数,并且这并不是通过四舍五入得到的整数,而是简单地去掉小数部分而得到的整数。例如,通过下面的代码分别计算10 除以3 和5 除以2,最终输出的运算结果依次为3 和2:

(2)进行求余运算时需要注意的问题。
当在整数类型数据和变量之间进行求余运算时,运算结果为数学运算中的余数。例如,通过下面的代码分别计算10 除以3 的余数、10 除以5 的余数和10 除以7 的余数,最终输出的运算结果依次为1、0 和3:

(3)关于0 的问题。
与数学运算一样,0 可以作为被除数,但是不可以作为除数。当0 作为被除数时,无论是除法运算,还是求余运算,运算结果都为0。例如,通过下面的代码分别计算0 除以6,以及0 除以6 的余数,最终输出的运算结果均为0:

当0 作为除数时,虽然可以编译成功,但是在运行时会抛出java.lang.ArithmeticException异常,即算术运算异常。
2.有小数参与运算
在对浮点类型数据或变量进行算术运算时,如果在算术表达式中含有double 型数据或变量,则运算结果为double 型,否则运算结果为float 型。
在对浮点类型数据或变量进行算术运算时,计算机计算出的结果在小数点后可能会包含n位小数,这些小数有时并不是精确的,而是会与数学运算中的结果存在一定的误差,只能是尽量接近数学运算中的结果。例如,在计算4.0减去2.1时,不同的数据类型会得到不同的计算结果,但是这些计算结果都会尽量接近或等于数学运算结果1.9,具体代码如下:

如果被除数为浮点型数据或变量,无论是除法运算,还是求余运算,0 都可以作为除数。如果是除法运算,则当被除数是正数时,运算结果为Infinity,表示无穷大,当被除数是负数时,运算结果为-Infinity,表示无穷小;如果是求余运算,则运算结果为NaN,例如:

3.1.3 关系运算符
关系运算符用于比较数据的大小,运算结果为boolean 型。当关系表达式成立时,运算结果为true;当关系表达式不成立时,运算结果为false。Java 中的关系运算符的功能及使用方法如表3.2 所示。
表3.2 关系运算符的功能及使用方法

从表3.2 中可以看出,所有关系运算符均可用于整数类型、浮点类型和字符类型数据的运算,其中,运算符 “==” 和 “!=” 还可用于boolean 型和引用数据类型数据的运算,即可用于所有的数据类型数据的运算。
学习笔记
要注意关系运算符 “==” 和赋值运算符 “=” 的区别!
3.1.4 逻辑运算符
逻辑运算符用于对boolean 型数据进行运算,运算结果仍为boolean 型。Java 中的逻辑运算符有 “!”(取反)、“^”(异或)、“&”(非简洁与)、“|”(非简洁或)、“&&”(简洁与)和 “||”(简洁或),下面将依次介绍各个运算符的用法和特点。
1.运算符 “!”
运算符 “!” 用于对逻辑值进行取反运算。当逻辑值为true 时,经过取反运算后的运算结果为false;当逻辑值为false 时,经过取反运算后的运算结果则为true,例如:

2.运算符 “^”
运算符 “^” 用于对逻辑值进行异或运算。当运算符的两侧同时为true 或false 时,运算结果为false;否则运算结果为true,例如:

3.运算符 “&&” 和 “&”
运算符 “&&” 和 “&” 均用于逻辑与运算。当运算符的两侧同时为true 时,运算结果为true;否则运算结果为false,例如:

运算符 “&&” 为简洁与运算符,运算符 “&” 为非简洁与运算符,它们的区别如下:
(1)只有在运算符 “&&” 左侧为true 时,才会运算其右侧的逻辑表达式,否则直接返回运算结果false。
(2)无论运算符 “&” 左侧为true 或false,都要运算其右侧的逻辑表达式,最后才会返回运算结果。
下面首先声明两个int 型变量x 和y,并分别将它们初始化为7 和5,然后运算表达式“(x<y)&&(x++==y--)”,并输出表达式的运算结果。在这个表达式中,如果运算符“&&” 右侧的表达式 “(x++=y--)” 被执行,则变量x 和y 的值将分别变为8 和4,并输出变量x 和y 的值,具体代码如下:

执行上面的代码,输出表达式的运算结果为false,输出变量x 和y 的值分别为7 和5,说明当运算符 “&&” 左侧为false 时,并不运算其右侧的表达式。下面将运算符 “&&” 修改为 “&”,具体代码如下:

执行上面的代码,输出表达式的运算结果为false,输出变量x 和y 的值分别为8 和4,说明当运算符 “&” 左侧为false 时,也要运算其右侧的表达式。
4.运算符 “||” 和 “|”
运算符 “||” 和 “|” 均用于逻辑或运算。当运算符的两侧同时为false 时,运算结果为false;否则运算结果为true,例如:

运算符 “||” 为简洁或运算符,运算符 “|” 为非简洁或运算符,它们的区别如下:
(1)只有在运算符 “||” 左侧为false 时,才会运算其右侧的逻辑表达式;否则直接返回运算结果true。
(2)无论运算符 “|” 左侧为true 或false,都要运算其右侧的逻辑表达式,最后才会返回运算结果。
下面首先声明两个int 型变量x 和y,并将它们分别初始化为7 和5,然后运算表达式“(x>y)||(x++==y--)”,并输出表达式的运算结果。在这个表达式中,如果运算符 “||” 右侧的表达式 “(x++==y--)” 被执行,则变量x 和y 的值将分别变为8 和4,并输出变量x 和y 的值,具体代码如下:

执行上面的代码,输出表达式的运算结果为true,输出变量x 和y 的值分别为7 和5,说明当运算符“||”左侧为true 时,并不运算其右侧的表达式。下面将运算符“||”修改为“|”,具体代码如下:

执行上面的代码,输出表达式的运算结果为true,输出变量x 和y 的值分别为8 和4,说明当运算符 “|” 左侧为true 时,也要运算其右侧的表达式。
3.1.5 位运算符
位运算是对操作数以二进制位为单位进行的操作和运算,运算结果均为整数类型。位运算符又分为逻辑位运算符和移位运算符。
1.逻辑位运算符
逻辑位运算符有 “~”(按位取反)、“&”(按位与)、“|”(按位或)和 “^”(按位异或),用来对操作数进行按位运算,它们的运算规则如表3.3 所示。
表3.3 逻辑位运算符的运算规则

按位取反运算是将二进制位中的0 修改为1,1 修改为0。在进行按位与运算时,只有当两个二进制位都为1 时,结果才为1。在进行按位或运算时,只要有一个二进制位为1,结果就为1。在进行按位异或运算时,当两个二进制位同时为0 或1 时,结果为0,否则结果为1。
【例3.1】 逻辑位运算符的运算规则。
下面是几个用来理解各个逻辑位运算符的运算规则的例子,具体代码如下:

上面代码中各表达式的运算过程分别如图3.1 ~图3.4 所示。

图3.1 表达式 “5&-4” 的运算过程

图3.2 表达式 “3|6” 的运算过程

图3.3 表达式 “10^3” 的运算过程

图3.4 表达式 “~(-14)” 的运算过程
2.移位运算符
移位运算符有 “<<”(左移,低位添0 补齐)、“>>”(右移,高位添符号位)和 “>>>”(无符号右移,高位添0 补齐),用来对操作数进行移位运算。
其中,“>>” 表示右移,若操作数为正数,则高位补0;若操作数为负数,则高位补1。“>>>” 表示无符号右移,也叫逻辑右移,无论操作数为正数还是负数,高位都补0。
【例3.2】 移位运算符的运算规则。
下面是几个用来理解各个移位运算符的运算规则的例子,具体代码如下:

上面代码中各表达式的运算过程分别如图3.5 ~图3.8 所示。

图3.5 表达式 “-2<<3” 的运算过程

图3.6 表达式 “15>>2” 的运算过程

图3.7 表达式 “4>>>2” 的运算过程

图3.8 表达式 “-5>>>1” 的运算过程
3.1.6 对象运算符
对象运算符(instanceof)用来判断对象是否为某一类型,运算结果为boolean 型。如果运算结果为boolean 型,则返回true;否则返回false。对象运算符的关键字为instanceof,它的应用形式如下:

例如:

3.1.7 其他运算符
在Java 中,除了前面介绍的几类运算符,还有一些不属于上述类别的运算符,它们的运算规则如表3.4 所示。
表3.4 其他运算符的运算规则

1.自动递增、递减运算符
与C、C++ 相同,Java 也提供了自动递增与递减运算符,其作用是自动将变量值加1或减1。它们既可以放在操作元的前面,也可以放在操作元的后面,根据运算符所在位置的不同,最终得到的运算结果也是不同的:在操作元前面的自动递增、递减运算符,会先将变量的值加1,再使该变量参与表达式的运算;在操作元后面的递增、递减运算符,会先使变量参与表达式的运算,再将该变量的值加1。例如:


学习笔记
自动递增、递减运算符的操作元只能为变量,不能为字面常数和表达式,而且该变量类型必须为整数类型、浮点类型或Java 包装类型。例如,++1、(num+2)++ 都是不合法的。
2.三元运算符 “?:”
三元运算符 “?:” 的应用形式如下:

三元运算符 “?:” 的运算规则为:若逻辑表达式的值为true,则整个表达式的值为表达式1 的值;否则为表达式2 的值。例如:

以上代码等价于下面的if…else 语句:

需要注意的是,对于三元运算符 “?:” 中的表达式1 和表达式2,只有其中的一个表达式会被执行,例如:

3.1.8 运算符的优先级及结合性
当在一个表达式中存在多个运算符,需要进行混合运算时,则会根据运算符的优先级来决定执行顺序。Java 中运算符的优先级如表3.5 所示。
表3.5 Java 中运算符的优先级

表3.5 所列运算符的优先级,由上而下优先级逐渐降低。其中,优先级最高的是之前未提及的括号 “()”,它的使用与数学运算中的括号一样,只是用来指定括号内的表达式要优先处理,括号内的多个运算符,仍然需要依照表3.5 的优先级顺序进行运算。
对于处在同一层级的运算符,需要按照它们的结合性,即 “先左后右” 还是 “先右后左” 的顺序来执行。在Java 中,除赋值运算符的结合性为 “先右后左” 以外,其他所有运算符的结合性都是 “先左后右”。