零基础学Java第三讲---运算符
一、什么是运算符
计算机的最基本的用途之⼀就是执行数学运算,如:
int a = 10;int b = 20;a + b;a < b;
上述 + 和 < 等就是运算符,即:对操作数进行操作时的符号,不同运算符操作的含义不同。
作为一门计算机语言,Java也提供了⼀套丰富的运算符来操纵变量。Java中运算符可分为以下:算术运算符(+ - * /)、关系运算符(< > ==)、逻辑运算符、位运算符、移位运算符以及条件运算符等。
二、算术运算符
1、基本四则运算符:加减乘除模(+ - * / %)
int a = 20;int b = 10;System.out.println(a + b); //30System.out.println(a - b); //10System.out.println(a * b); //200System.out.println(a / b); //2System.out.println(a % b); // 0 --->模运算相当于数学中除法的余数
#注:
(1)都是⼆元运算符,使用时必须要有左右两个操作数
(2)int/int结果还是int类型,而且会向下取整
int a = 3;int b = 2;// 在数学中应该是1.5 但是在Java中输出结果为1,会向下取整,即⼩数点之后全部舍弃掉了 System.out.println(a / b);// 如果要得到数学中的结果,可以使⽤如下⽅式 double d = a*1.0 / b;System.out.println(d);
(3)做除法和取模时,右操作数不能为0
int a = 1;int b = 0;System.out.println(a / b)// 运⾏结果 Exception in thread "main" java.lang.ArithmeticException: / by zeroat Test.main(Test.java:5)
(4)%不仅可以对整型取模,也可以对double类型取模,但是没有意义,⼀般都是对整型取模的
System.out.println(11.5 % 2.0);// 运⾏结果: 1.5
(5)两侧操作数类型不⼀致时,向类型大的提升
System.out.println(1+0.2); // +的左侧是int,右侧是double,在加之前int被提升为double 故:输出1.2
2、增量运算符 += -= *= %= /=
该种类型运算符操作完成后,会将操纵的结果赋值给左操作数。
int a = 1;a += 2; // 相当于 a = a + 2
System.out.println(a); // 输出3a -= 1; // 相当于 a = a - 1
System.out.println(a); // 输出2 a *= 3; // 相当于 a = a * 3
System.out.println(a); // 输出6 a /= 3; // 相当于 a = a / 3
System.out.println(a); // 输出2 a %= 3; // 相当于 a = a % 2
System.out.println(a); // 输出2
#注:增量运算符在计算的时候,可以不进行强制类型转换
double a = 10.4;
int b = 10;
b += a; //不会报错
b = b + a; //此时会编译报错,等号右边被提升为了double类型
3、自增/自减运算符 ++ --
++是给变量的值+1,--是给变量的值-1。
int a = 1;
a++; // 后置++ 表示给a的值加1,此时a的值为2
System.out.println(a++); // 注意:后置++是先使⽤变量原来值,表⽰式结束时给变量+1,因此输出2 System.out.println(a); // 输出3 ++a; // 前置++ 表⽰给a的值加1
System.out.println(++a); // 注意:前置++是先给变量+1,然后使⽤变量中的值,因此输出5
System.out.println(a); // 输出5 // --操作符给操作-1,与++含义类似
#注:
(1)如果单独使用,前置++和后置++没有任何区别
(2)如果混合使用,前置++先+1,然后使用变量+1之后的值,后置++先使用变量原来的值, 表达式结束时给变量+1
(3)只有变量才能使用自增/自减运算符,常量不能使用,因为常量不允许被修改
三、关系运算符
关系运算符主要有六个: == != < > <= >= ,其计算结果是true或者false。
int a = 10;
int b = 20;
// 注意: 在Java中 = 表示赋值,要与数学中的含义区分
// 在Java中 == 表示相等
System.out.println(a == b); //false
System.out.println(a != b); //true
System.out.println(a < b); //true
System.out.println(a > b); //false
System.out.println(a <= b); //true
System.out.println(a >= b); //false
#注:当需要多次判断时,不能连着写,如:3
四、逻辑运算符
逻辑运算符主要有三个: && || ! ,运算结果都是boolean类型。
1、逻辑与&&
(1)语法规则:表达式1&&表达式2,左右表达式必须是boolean类型的结果。
(2)相当于现实生活中的且,如:如果是学生,并且带有学生证才可以享受半票。
(3)两个表达式都为真,结果才是真,只要有⼀个是假,结果就是假。
int a = 1;
int b = 2;System.out.println(a == 1 && b == 2); // 左为真且右为真则结果为真
System.out.println(a == 1 && b > 100); // 左为真但右为假则结果为假
System.out.println(a > 100 && b == 2); // 左为假但右为真则结果为假
System.out.println(a > 100 && b > 100); // 左为假且右为假则结果为假
2、逻辑或 ||
(1)语法规则:表达式1||表达式2,左右表达式必须是boolean类型的结果。
(2)相当于生活中的或者,如:出门买东西付钱,微信或者现金都可以。
(3)两个表达式只要有一个为真,结果就为真,都为假,结果才是假
int a = 1;
int b = 2;System.out.println(a == 1 || b == 2); // 左为真且右为真则结果为真
System.out.println(a == 1 || b > 100); // 左为真但右为假则结果为真
System.out.println(a > 100 || b == 2); // 左为假但右为真则结果为真
System.out.println(a > 100 || b > 100); // 左为假且右为假则结果为假
3、逻辑非!
真变假,假变真。
4、短路求值
&&和||均遵守短路求值的规则
System.out.println(10 > 20 && 10 / 0 == 0); // 打印false
System.out.println(10 < 20 || 10 / 0 == 0); // 打印true
我们都知道,计算10 / 0 会导致程序抛出异常.但是上面的代码却能正常运行,说明 10 / 0 并没有真正被求值。
#注:
(1)对于&&,如果左侧表达式值为false,则表达式结果⼀定是false,无需计算右侧表达式.
(2)对于||,如果左侧表达式值为true,则表达式结果⼀定是true,无需计算右侧表达式.
(3)&和|如果表达式结果为boolean时,也表示逻辑运算.但与&&和||相比,它们不支持短路求值.
System.out.println(10 > 20 & 10 / 0 == 0); // 程序抛出异常
System.out.println(10 < 20 | 10 / 0 == 0); // 程序抛出异常
五、位运算符
Java 中数据存储的最小单位是字节,而数据操作的最小单位是比特位.字节是最小的存储单位,每个字节是由8个⼆进制比特位组成的,多个字节组合在⼀起可以表示各种不同的数据。
位运算符主要有四个: & | ~ ^ ,除 ~ 是⼀元运算符外,其余都是⼆元运算符。
位操作表示按⼆进制位运算.计算机中都是使用⼆进制来表示数据的(01构成的序列),按位运算就是在按照⼆进制位的每⼀位依次进行计算.
1、原码、反码、补码
位运算中我们要用到原反补码操作
(1)原码:将我们常见的10进制转换为2进制(假设一共8位),最高为表示符号,其余位表示数值(如10==>00001010,-10==>10001010)
(2)反码:将原码保持符号位不变,其他位依次按位取反(0变1,1变0)(如10==>01110101,-10==>11110101)
(3)补码:将反码+1得到的结果(如10==>01110110,-10==>1110110)
#注:
(1)符号位0表示正,1表示负
(2)所有的位运算操作都是操作补码!!!
(3)只有负数才需要进行转换操作,正数的原码=反码=补码!!!
(4)在运算结束后,得到的结果是补码,如果符号位是0,那就直接返回即可,但是若符号位是1,那就要将这个补码转换成反码,最后转换成原码返回(补==>反==>原)
2、按位与&
如果两个⼆进制位都是1,则结果为1,否则结果为0
int a = 10;
int b = 20;
System.out.println(a & b);
进行按位运算,需要先把10和20转成⼆进制,分别为1010和10100
3、按位或|
如果两个⼆进制位都是0,则结果为0,否则结果为1
int a = 10;
int b = 20;
System.out.println(a | b);
运算方式和按位与类似.
#注:当&和|的操作数为整数(int,short,long,byte)的时候,表示按位运算,当操作数为boolean的时候,表示逻辑运算.
4、按位取反~
如果该位为0则转为1,如果该位为1则转为0
int a = 0xf;
System.out.printf("%x\n", ~a)
#注:
(1)0x前缀的数字为十六进制数字.十六进制可以看成是⼆进制的简化表示方式.⼀个十六进制数字对应4个⼆进制位
(2)0xf表示10进制的15,也就是⼆进制的1111
(3)printf 能够格式化输出内容,%x表示按照十六进制输出
(4)\n表示换行符
5、按位异或^
如果两个数字的⼆进制位相同,则结果为0,相异则结果为1
int a = 0x1;
int b = 0x2;
System.out.printf("%x\n", a ^ b);
#注:如果两个数相同,则异或的结果为0(这个要记住,后续的刷题会用到)
六、移位运算
移位运算符有三个: << >> >>> ,都是⼆元运算符,且都是按照⼆进制比特位来运算的
1、左移<<
最左侧位不要了,最右侧补0
int a = 0x10;
System.out.printf("%x\n", a << 1);// 运⾏结果(注意, 是按⼗六进制打印的)
20
#注:向左移位时,丢弃的是符号位,因此正数左移可能会变成负数。
2、右移>>
最右侧位不要了,最左侧补符号位(正数补0,负数补1)
int a = 0x10;
System.out.printf("%x\n", a >> 1);// 运⾏结果(注意, 是按⼗六进制打印的)
8int b = 0xffff0000;
System.out.printf("%x\n", b >> 1);// 运⾏结果(注意, 是按⼗六进制打印的)
ffff8000
3、无符号右移>>>
最右侧位不要了,最左侧补0
int a = 0xffffffff;
System.out.printf("%x\n", a >>> 1);// 运⾏结果(注意, 是按⼗六进制打印的)
7fffffff
#注:
(1)左移1位,相当于原数字*2.左移N位,相当于原数字*2的N次方.【针对正数而言】
(2)右移1位,相当于原数字/2.右移N位,相当于原数字/2的N次方.【针对正数而言】
(3)由于计算机计算移位效率高于计算乘除,当某个代码正好乘除2的N次方的时候可以用移位运算代替.【针对正数而言】
(4)移动负数位或者移位位数过大都没有意义
七、条件运算符
条件运算符只有⼀个:
表达式 1 ? 表达式 2 : 表达式 3
当表达式1的值为true时,整个表达式的值为表达式 2 的值;
当表达式1的值为false时,整个表达式的值为表达式 3 的值.
也是Java中唯⼀的⼀个三目运算符,是条件判断语句的简化写法.
#注:
(1)表达式2和表达式3的结果要是同类型的,除非能发生类型隐式类型转换
int a = 10;
int b = 20;
int c = a > b? 1 : 2.0;
(2)表达式不能单独存在,其产生的结果必须要被使用
int a = 10;
int b = 20;
a > b? a : b; // 报错:Error:(15, 14) java: 不是语句
八、运算符的优先级
在⼀条表达式中,各个运算符可以混合起来进行运算,但是运算符的优先级不同,如:*和/的优先级要高于+和-,有些情况下稍不注意,可能就会造成很大的麻烦
// 求a和b的平均值
int a = 10;
int b = 20;
int c = a + (b - a) >> 1;
System.out.println(c);
上述表达式中,由于+的优先级要高于>>,因此a先和b-a的结果做加法,整体为20,最后再进行右移,因此结果为10。
#注:
运算符之间是有优先级的.具体的规则我们不必记忆,即日后的编程过程中,如果有不确定的,直接加上
// 求a和b的平均值
int a = 10;
int b = 20;
int c = a + ((b - a) >> 1);
System.out.println(c);