算术运算符
加法运算符
// 当做加法运算符
double d1 = 3;
double d2 = 2;
// 5.0
d1 + d2;
// 当做字符串的连接运算符
"a" + 1;
减法运算符
// 当做减法运算符
double d1 = 3;
double d2 = 2;
// 1.0
d1 - d2;
// 求负运算
double x = -5.0;
x = -x;
乘法运算符
double d1 = 3;
double d2 = 2;
// 6.0
d1 * d2;
除法运算符
// 浮点数的除法可以获取到自然的计算结果
double d1 = 3;
double d2 = 2;
// 1.5
d1 / d2;
// 如果两个数都是整数,则计算结果也是整数
// 就是将自然除法的结果截断取整
int i1 = 10;
int i2 = 3;
// 3
i1 / i2
// 正整数除以浮点数0.0会得到正无穷大,Infinity
double d1 = 3;
double d2 = 0;
d1 / d2
// 负整数除以浮点数0.0会得到负无穷大,-Infinity
double d1 = -3;
double d2 = 0;
d1 / d2
// 整数除以0会出现算术异常 java.lang.ArithmeticException: / by zero
int i1 = 10;
int i2 = 0;
// 报错
i1 / i2
求余运算符
它的计算结果是使用第一个操作数除以第二个操作数,得到一个整除的结果后剩下的值就是余数。
double d1 = 5.2;
double d2 = 3.1;
// 结果为2.1
d1 % d2;
// 输出非数,NaN
5 % 0.0;
-5 % 0.0;
// 输出0.0
0 % 5.0;
// 输出非数,NaN
0 % 0.0;
// 出现算术异常
-5 % 0;
自加和自减
只能操作变量。
1. 自加或自减是单目运算符,只能操作一个操作数。
2. 自加或自减运算符只能操作单个数值型(整型、浮点数)的变量,不能操作常量或表达式。
3. 运算符出现在左边是先把操作数加或减1,然后才把操作数放入表达式中运算。
左边的自加
// 自加
int a = 5;
// 6+6
int b = ++a +6;
// 6
System.out.println(a);
// 12
System.out.println(b);
左边的自减
// 自减
int a = 5;
// 4+6
int b = --a +6;
// 4
System.out.println(a);
// 10
System.out.println(b);
- 运算符出现在右边是先把操作数放入表达式中运算,然才把操作数加1。
右边的自加
int a = 5;
// 5+6
int b = a ++ +6;
// 6
System.out.println(a);
// 11
System.out.println(b);
右边的自减
// 自减
int a = 5;
// 5+6
int b = a -- +6;
// 4
System.out.println(a);
// 11
System.out.println(b);
赋值运算符
赋值运算符(=)用于为变量指定变量值。
将直接量赋值给变量
String str = "Java";
将一个变量的值赋给另一个变量
String str1 = str;
连续赋值
int a;
int b;
int c;
// 通过为a、b、c赋值,三个变量的值都是7
a = b = c = 7;
给表达式赋值
double d1 = 12.34;
double d2 = d1 + 5;
位运算符
位运算符只能操作整数类型的变量或值。int数值在内存里都是32位的数值。
按位与
当两位同时为1时才返回1
示例1
// 输出1
System.out.println(5 & 9);
计算过程如下
// 5
00000000000000000000000000000101
// 9
00000000000000000000000000001001
// 按位或后的结果,1
00000000000000000000000000000001
按位或
只有一位为1即可返回1
示例1
// 输出1
System.out.println(5 | 9);
计算过程如下
// 5
00000000000000000000000000000101
// 9
00000000000000000000000000001001
// 按位或后的结果,13
00000000000000000000000000001101
按位非
单目运算符,将操作数的每个位(包括符号位)全部取反
示例1
// 输出4
System.out.println(~-5);
计算过程如下
// -5的原码
10000000000000000000000000000101
// -5的反码
11111111111111111111111111111010
// -5的补码,加1得到
// 负数在计算机里以补码的形式存在
11111111111111111111111111111011
// 进行按位非操作,即全部取反,即4
00000000000000000000000000000100
按位异或
当两位相同时返回0,不同时返回1
示例1
// 输出1
System.out.println(5 ^ 9);
计算过程如下
// 5
00000000000000000000000000000101
// 9
00000000000000000000000000001001
// 按位或后的结果,12
00000000000000000000000000001100
左移运算符
将操作数的二进制码整体左移移动指定位数,左移后右边空出来的位以0填充。
System.out.println(5 << 2);
计算过程如下
// 左移2位
00000000000000000000000000000101
// 左移并填充后
00000000000000000000000000010100
// -5的补码
11111111111111111111111111111011
// 左移2位,得-20
11111111111111111111111111101100
右移运算符
- >>运算符是把第一个操作数的二进制码右移指定位数后,左边空出来的位以原来的符号位填充,即如果第一个操作数原来是正数,则左边补0,如果第一个操作数是负数,则左边补1。
// -5向右移动2位,得-2
System.out.println(-5 >> 2);
计算过程
// -5的补码
11111111111111111111111111111011
// 右移2位并用符号位填充后的补码,
11111111111111111111111111111110
// 减去1得到反码
11111111111111111111111111111101
// 取反得到原码
10000000000000000000000000000010
无符号右移运算符
- >>>是无符号右移运算符,它把第一个操作数的二进制码右移指定位数后,左边空出来的位总是以0填充。
// -5向右无符号移动2位,得1073741822
System.out.println(-5 >>> 2);
计算过程
// -5的补码
11111111111111111111111111111011
// 向右无符号移动2位
// 变成了正数,1073741822
00111111111111111111111111111110
位移运算的其他规则
- 对于低于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位),得到的结果才是真正移位的位数。 - 当进行移位运算时,只要被移位的二进制码没有发生有效位的数字丢失(对于正数而言,通常指被移出的位全部都是0),不难发现左移n位就相当于乘以2的n次方,右移n位则是除以2的n次方,不仅如此,进行位移运算不会改变操作数本身,只是得到了一个新的运算结果,而原来的操作数本身是不会改变的。
扩展后的赋值运算符
赋值运算符可以与算术运算符、位移运算符结合,扩展成功能更加强大的运算符,列表如下:
扩展赋值运算符 | 扩展前 | 扩展后 |
---|---|---|
+= | x += y; | x = x + y; |
-= | x -= y; | x = x - y; |
*= | x *= y; | x = x * y; |
/= | x /= y; | x = x / y; |
%= | x %= y; | x = x % y; |
&= | x &= y; | x = x & y; |
|= | x |= y; | x = x | y; |
^= | x ^= y; | x = x ^ y; |
<<= | x <<= y; | x = x << y; |
<<<= | x <<<= y; | x = x <<< y; |
>>= | x >>= y; | x = x >> y; |
比较运算符
- >:大于,只支持左右两边操作数是数值类型。
- >=:大于等于,只支持左右两边操作数是数值类型。
- <:小于,只支持左右两边操作数是数值类型。
- <=:小于等于,只支持左右两边操作数是数值类型。
- ==:等于,如果进行比较的两个操作数都是数值类型,即使它们的数据类型不相同,只要它们的值相等,也都将返回true。
// 返回true
97 =='a'
// 返回true
5.0 == 5
如果两个操作数都是引用类型,那么只有当两个引用变量的类型具有父子关系时才可以比较,而且这两个引用必须指向同一个对象才会返回true。
String s1 = new String();
String s2 = new String();
// 返回false,因为不是一个对象
System.out.println(s1 == s2);
String s3 = s1;
// 返回true,因为来自一个对象
System.out.println(s3 == s1);
Java也支持两个boolean类型的值进行比较,例如:
true == false
将返回false。
基本类型的变量和值不能和引用类型的变量、值使用==进行比较
boolean类型的变量、值不能与其他任意类型的变量、值使用==进行比较。
- !=:不等于,如果进行比较的两个操作数都是数值类型,即使它们的数据类型不相同,只要它们的值不相等,也都将返回true。
如果两个操作数都是引用类型,那么只有当两个引用变量的类型具有父子关系时才可以比较,而且这两个引用必须指向同一个对象才会返回true。
逻辑运算符
逻辑运算符用于操作两个布尔型的变量或常量,列表如下:
&&(与)
前后两个操作数必须都是true才返回true,否则返回false
// 输出true
// '6'转化为整数54
System.out.println(5 > 3 && '6' > 10);
&(不短路与)
作用于&&相同,但不会短路。
||(或)
只要两个操作数中有一个是true,就可以返回true,否则返回false。
// 输出true
// 4>=5返回false,'c'>'a'返回true
System.out.println(4 >= 5 || 'c' > 'a');
int a = 5;
int b = 10;
// 对a > 4和b++ > 10求或运算
// 在这里发生了短路,所以b++没有执行
if (a > 4 || b ++> 10)
{
// 输出a的值是5,b的值是11
System.out.println("a的值是:" + a + ",b的值是:" + b);
}
|(不短路或)
作用于|相同,只是不会短路。
int a = 5;
int b = 10;
// 对a > 4和b++ > 10求或运算
if (a > 4 | b ++> 10)
{
// 输出a的值是5,b的值是11
System.out.println("a的值是:" + a + ",b的值是:" + b);
}
!(非)
只需要一个操作数,如果操作数为true,则返回false,如果操作数为false,则返回true。
// 输出true
System.out.println(!false);
^(异或)
当两个操作数不同时才返回true,如果两个操作数相同则返回false。
// 返回true
// 4>=5返回false,'c'>'a'返回true
System.out.println(4 >= 5 ^ 'c' > 'a');
三目运算符
语法格式如下:
(expression) ? if-true-statement : if-false-statement;
先对逻辑表达式expression求值,如果逻辑表达式返回true,则返回第二个操作数的值,如果逻辑表达式返回false,则返回第三个操作数的值。
// 将输出“5大于3”
String str = 5 > 3 ? "5大于3" : "5小于3";
嵌套的三目运算符
int a = 10;
int b = 20;
// 嵌套三目运算符
System.out.println(a > b ? "a大于b" : (a < b ? "a小于b" : "a等于b"));
运算符的结合性和优先级
Java语言中大部分运算符是从左向右结合的,只有单目运算符、赋值运算符和三目运算符例外。