运算符
这里只记录特殊的点,通用的那些就没必要记了。
1. 算术运算符
除法/
:如果除法运算符的两个操作数中含浮点数,则计算结果也是浮点数,其就是自然除法的结果。而且此时允许除数是 0 或者 0.0,得到结果是正无穷大或负无穷大。
求余%
:其结果是使用第一个操作数除以第二个操作数,得到一个整除的结果后剩下的值。
- 即它不完全等同于其他语言中的求余运算,不要求操作数均是整数。
- 特殊地,若操作数含浮点数且第二个操作数的数值是 0,求余运算的结果是非数
NaN
。 Math.floorMod
方法有类似的效果,其推出的目的是解决一个长期存在的有关整数余数的问题。- 考虑表达式
n % 2
,所有人都知道,如果n是偶数,结果为0;如果n为奇数,结果为1;但是,如果n为“负奇数”,结果为-1。 - 为何这么奇怪?设计最早的计算机时,必须有人制定规则,明确整数除法和求余对负数操作数该如何处理。尽管数学家们几百年来都知道这样一个最优规则:$余数\ge0$,然而最早制定规则的人并没有翻译数学书好好研究,而是提出了一些看似合理但实际上很不方便的规则。
- 考虑表达式
Java 没有提供其他更复杂的运算符,若需要完成乘方、开方等运算,可借助于 java.lang.Math
类的工具方法完成复杂的数学运算:

strictfp
关键字:
- 修饰方法,该方法使用严格的浮点计算来生成可再生的结果。
- 修饰类,该类中所有方法都使用严格的浮点计算。
2. 赋值运算符
值得指出的是,赋值表达式是有值的,其值就是右边被赋的值。如 String str2 = str
这整个式子就具有一个 str
的值。是故,赋值运算符支持连续赋值,通过使用多个赋值运算符,可以一次为多个变量赋值:
int a;
int b;
int c;
// 通过为a,b,c赋值,三个变量的值都是7
a = b = c = 7;
然而,不要被上述说明迷惑了,如果连续赋值中的变量尚未被定义,是不能连续赋值的,比如如下操作将会报错:
// 试图在定义式中使用连续赋值同时定义多个变量,将会报错,提示找不到变量c,b
int a = b = c = 7;
3. 位运算符
Java 支持 7 个位运算符,一般来说,位运算符只能操作整数类型的变量或值:
&
:按位与。当两位同时为1时才返回1。|
:按位或。只要有一位为1即可返回1。~
:按位非。单目运算符,将操作数的每个位(包括符号位)全部取反。^
:按位异或。当两位相同时返回0,不同时返回1。<<
:左移运算符。>>
:右移运算符。把第一个操作数的二进制码右移指定位数后,左边空出来的位以原来的符号位填充。即:若原来为正,左边补 0;原来为负,左边补 1。>>>
:无符号右移运算符。把第一个操作数的二进制码右移指定位数后,左边空出来的位总是以 0 填充
Java 移位运算时还有如下规则:
- 对于低于
int
类型(如byte, short, char
) 的操作数总是先自动类型转换为int
类型后再移位。 - 对于
int
类型的整数移位后 a>>b,当 b>32 时,系统先用 b 对 32 求余(因为int
类型只有 32 位),得到的结果才是真正移位的位数。例如,a>>33 和 a>>1 的结果完全一样,而 a>>32 的结果和 a 相同。 - 同上,对于
long
类型的整数移位 a>>b ,当 b>64 时,总是先用 b 对 64 求余(因为long
类型是 64 位) ,得到的结果才是真正移位的位数。
应用在布尔值上时,&
和|
运算符也会得到一个布尔值。这些运算符与&&
和||
运算符很类似,不过&
和|
运算符不采用“短路”求值,也就是说,得到计算结果之前两个操作数都需要计算。
4. 扩展后的赋值运算符

只要能使用这些运算符,通常都推荐使用它们,因为这种运算符不仅具有更好的性能,而且程序会更加健壮;
运行下面程序,不难发现 a=a+5
和 a+=5
虽然运行结果相同,但底层的运行机制存在一定差异:
// 定义一个byte类型的变量
byte a = 5;
// 下面语句出错,因为5默认是int类型,a + 5就是int类型
// 把int类型赋给byte类型的变量,所以出错
// a = a + 5;
// 定义一个byte类型的变量
byte b = 5;
// 下面语句不会出现错误
b += 5;
5. 比较运算符
>,>=,<,<=
只支持左右两边操作数都是数值类型的比较,且不计较具体数据类型,即 int
和 float
的组合也能比较。
==,!=
对数值类型的比较同上,但它们还支持引用类型的比较。以==
为例:
等于
==
:- 基本类型的变量/值不能和引用类型的变量/值使用
==
进行比较; boolean
类型的变量、值不能与其他任意类型的变量、值使用==
进行比较;- 如果两个引用类型之间没有父子继承关系,它们的变量也不能使用
==
进行比较。 - 因为 Java 只有值传递,所以,对于
==
来说,不管是比较基本数据类型,还是引用数据类型的变量,其本质比较的都是值,只是引用类型变量存的值是对象的地址。
- 基本类型的变量/值不能和引用类型的变量/值使用
类型 数值类型 只要它们的值相等,即为 true,即使其数据类型不同 97=='a' // true
5.0==5 // true
引用类型 只有当两个引用变量的类型具有父子关系时才可比较,当这两个引用指向同一个对象才会返回 true boolean
类型java 也支持两个 boolean
类型的值进行比较true==false //false
值得注意的是,Java 为所有的基本数据类型都提供了对应的包装类,关于包装类实例的比较有些特殊。
6. 逻辑运算符
&&
:与。&
:不短路与。||
:或。|
:不短路或。!
:非。^
:异或。
7. 三目运算符
expression ? If-true-statement : if-false-statement;
其中expression
的结果必须为boolean
类型。
8. 运算符的结合性和优先级
运算符的结合性和优先级:所有的数学运算都认为是从左向右运算的,Java中大部分运算符也是从左向右结合的,只有单目运算符、赋值运算符和三目运算符例外,它们三个是从右向左结合的,也就是从右向左运算。下表按运算符优先级从高到底自上至下排列:
