运算符
运算符分为算术运算符、关系运算符、逻辑运算符、位运算符、移位运算符、条件运算符等等。
算术运算符
基本四则运算符:加、减、乘、除、模(+、-、*、\、%)
public static void main(String[] args) {
int a = 10;
int b = 20;
System.out.println(a + b); // 30
System.out.println(a - b); // -10
System.out.println(a * b); // 200
System.out.println(a / b); // 0
System.out.println(a % b); // 10
}
注意:
- 都是二元运算符,使用时必须要有左右两个操作数
- int / int 结果还是int类型,会向下取整,也就是省略小数点后的数
- 做除法和取模时,右操作数不能为0
- %不仅可以对整数取模,也可以对double类型取模,但是没有意义,一般对整型取模
- 两侧操作数类型不一致时,向类型大的提升
public static void main(String[] args) {
int a = 10;
double b = 5.5;
System.out.println(a - b); //结果为4.5,double类型,int先被提升为double,double - double = double
}
增量运算符:+=、-=、*=、/=、%=
public static void main(String[] args) {
int a = 10;
a += 10; //a = a + 10;
a -= 10; //a = a - 10;
a /= 10; //a = a / 10;
a *= 10; //a = a * 10;
a %= 10; //a = a % 10;
}
注意:只有变量才能使用,因为常量不能修改。
自增/自减运算符(++ / --)
++是给变量的值+1,–是给变量的值减一。
public static void main(String[] args) {
int a = 1;
a++; //此时a = 2
System.out.println(a++);//后置++,先输出a的值为2,再进行加一,a的值变为3
System.out.println(a);//此时a的值为3
int b = 1;
++b; //此时 b = 2
System.out.println(++b);//前置++,先对 b 进行加 1,在输出b的值,所以b = 3,输出3
System.out.println(b);//此时a的值为3
//前置--与后置-- 跟++类似
}
注意:
- 如果单独使用,前置++与后置++没什么区别
- 如果混合使用,前置++先加1,然后使用变量+1后的值,后置++先使用变量原来的值,表达式结束时给变量+1
- 只有变量才能使用自增/自减运算符,常量不能使用,因为常量不能被修改
关系运算符
关系运算符主要有六个:==,!=,<, >,<=,>=,其计算结果为true或false
public static void main(String[] args) {
int a = 10;
int b = 20;
System.out.println(a > b);//false
System.out.println(a < b);//true
System.out.println(a == b);//false
System.out.println(a != b);//true
System.out.println(a <= b);//true
System.out.println(a >= b);//false
}
注意:当需要多次判断时,不能连着写,如3 < a < 10,应该使用逻辑运算符。
逻辑运算符
逻辑运算符主要有三个:&&,||,!,其运算结果都是boolean类型。
逻辑与&&
语法规则:表达式1 && 表达式2,左右表达式必须是boolean类型的结果
两个表达式都为真,即为真,只要有一个为假,即为假。
表达式1 | 表达式2 | 结果 |
---|---|---|
真 | 真 | 真 |
假 | 真 | 假 |
真 | 假 | 假 |
假 | 假 | 假 |
public static void main(String[] args) {
int a = 10;
int b = 20;
System.out.println(a == 10 && b == 20); //true
System.out.println(a == 10 && b < 10); //false
System.out.println(a < 0 && b == 20); //false
System.out.println(a < 0 && b < 10); //false
}
逻辑或||
语法规则:表达式1 || 表达式2,左右表达式必须是boolean类型的结果
两个表达式都为假,即为假,但只要有一个为真,即为真。
表达式1 | 表达式2 | 结果 |
---|---|---|
真 | 真 | 真 |
假 | 真 | 真 |
真 | 假 | 真 |
假 | 假 | 假 |
public static void main(String[] args) {
int a = 10;
int b = 20;
System.out.println(a == 10 || b == 20); //true
System.out.println(a == 10 || b < 10); //true
System.out.println(a < 0 || b == 20); //true
System.out.println(a < 0 || b < 10); //false
}
逻辑非!
语法规则:!表达式
表达式为真,即为假;表达式为假,即为真。
表达式 | !表达式(结果) |
---|---|
真 | 假 |
假 | 真 |
public static void main(String[] args) {
int a = 10;
System.out.println(!(a==10));//false
System.out.println(!(a!=10));//true
}
短路求值
什么是短路求值
&& 和 || 支持短路求值
对于&&,如果左侧表达式值为false,则表达式结果一定是false,无需计算右侧表达式
对于||,如果左侧表达式值为true,则表达式结果一定为true,无需计算右侧表达式
举个例子,首先给大家介绍个异常,当我们使用算术运算符 \ 来除以0是会报算术异常的
public static void main(String[] args) {
int a = 10;
System.out.println(a / 0);
}
public static void main(String[] args) {
int a = 10;
System.out.println((a != 10) && (a / 0 == 0));
//因为短路求值,a!=10结果为false,所以最终结果为false,
// 所以a/0没有被真正求值,所以没有报算术异常,而是输出false
}
public static void main(String[] args) {
int a = 10;
System.out.println((a == 10) || (a / 0 == 0));
//因为短路求值,a==10结果为true,所以最终结果为true,
// 所以a/0没有被真正求值,所以没有报算术异常,而是输出true
}
注意:
如果& 和 | 两边的表达式结果为boolean类型时,也表示逻辑运算,但与&&与||相比,它们不支持短路求值
public static void main(String[] args) {
int a = 10;
System.out.println((a == 10) | (a / 0 == 0));//程序报异常
System.out.println((a != 10) & (a / 0 == 0));//程序报异常
}
位运算符
java中数据存储的最小单位是字节,数据操作的最小单位是比特,字节是由8个比特位组成。位操作表示按二进制位运算,就是按照二进制位的每一位依次运算。
位运算符主要有四个:&、|、~、^,除 ~ 是一元运算符外,其余都是二元运算符。
按位与:&
按位与:如果两个二进制位都是1,结果为1,否则,结果为0
public static void main(String[] args) {
int a = 10;
int b = 20;
System.out.println(a & b);
}
10 的二进制是: 0000 1010
20 的二进制是: 0001 0100
0000 1010
0001 0100 (&)
——————
0000 0000
按位或:|
按位或:如果两个二进制位都是0,结果为0,否则,结果为1
public static void main(String[] args) {
int a = 10;
int b = 20;
System.out.println(a | b);
}
10 的二进制是: 0000 1010
20 的二进制是: 0001 0100
0000 1010
0001 0100 (|)
——————
0001 1110
结果为30
注意:当&和|的操作数为整数(int,short,byte,long)的时候,表示按位操作,当操作数为boolean的时候,为逻辑运算。
按位取反:~
按位取反:就是如果该位为0则取为1,如果该位为1则取为0
public static void main(String[] args) {
int a = 0Xf;
System.out.println(~a);//fffffff0,int是四个字节,
//a为0x0000000f,~a = 0xfffffff0
}
按位异或:^
按位异或:如果两个数的二进制位相同,则为0,否则为1。
public static void main(String[] args) {
int a = 1;
int b = 2;
System.out.println(a ^ b);
}
1 的二进制是: 0000 0001
2 的二进制是: 0000 0010
0000 0001
0000 0010 (^)
——————
0000 0011
结果为3
移位运算符
移位运算符有三个:<< >> >>>,都是二元运算符,且都是按照二进制比特位进行运算的
左移:<<
左移:最左侧位舍去,最右位补0。
public static void main(String[] args) {
int a = 10;
System.out.println(a << 1);
}
10 的二进制是: 0000 1010
左移1位: 0001 0100
结果为20
注意:左移丢弃的是符号位,所以正数左移之后可能为负数。
右移:>>
右移:最右侧位舍去,最左位补符号位(正数补0,负数补1)。
public static void main(String[] args) {
int a = 10;
System.out.println(a >> 1);
}
10 的二进制是: 0000 1010
左移1位: 0000 0101
结果为5
无符号右移
无符号右移:最右侧位舍去,最左位补0。
public static void main(String[] args) {
int a = 0xffffffff;
System.out.printf("%x",a >>> 1);
}
右移补0:0x 0111 1111 1111 1111 1111 1111 1111 1111
所以结果:0x 7 f f f f f f f
注意:
- 左移一位,相当于原数字 * 2. 左移N位,相当于原数字 * 2 的N次方
- 左移一位,相当于原数字 / 2. 左移N位,相当于原数字 / 2 的N次方
- 由于计算机计算移位效率高于计算机乘除,当需要实现某个数乘以2的N次方,可以用移位运算代替。
条件运算符
条件运算符:布尔表达式1 ? 表达式2 :表达式3
当布尔表达式为真,则整个表达式的值为表达式2的值
当布尔表达式为假,则整个表达式的值为表达式3的值
这是java中唯一的一个三目运算符
public static void main(String[] args) {
int a = 10;
int b = 20;
int ret = a > b ? a : b;
System.out.println(ret);
}
结果为20
注意:
- 表达式2和表达式3的结果要是同一个类型的,除非能发生隐式类型转换
- 表达式不能单独存在,其产生的结果必须要被使用
public static void main(String[] args) {
int a = 10;
int b = 20;
a > b ? a : b;//报错
}
运算符的优先级
在表达式中,多个运算符可以混合使用,但是优先级的运算符优先级不同,比如* 、/ 的优先级大于+、-,所以计算时会优先计算,如果不注意,可能会造成结果错误,造成不必要的麻烦。
public static void main(String[] args) {
int a = 10;
int b = 20;
int ret = a + (b - a) >> 1;//本意是为了求平均数
System.out.println(ret);
}
结果却是10
为什么呢?
因为+ 的优先级大于 >> 所以先算a + (b - a) 结果为20,20左移1位为 10
对于运算符的优先级我们没必要强加记忆,我们可以在使用中熟练,并在产生歧义的代码加上括号,避免出错,也便于程序员直观检查和理解。
public static void main(String[] args) {
int a = 10;
int b = 20;
int ret = a + ((b - a) >> 1);
System.out.println(ret);
}
—————————————————————————————————————
今天java运算符我们就学到这里,不积跬步,无以至千里,我们一起慢慢进步!