5. 运算符 p34~p40
5.1 算数运算符
知识:
- 加减乘除模
- 小tip:如果在取模的运算中有负号,结果与被模数符号相同
public class ArithmeticTest1 {
public static void main(String[] args) {
int a = 3;
int b = 4;
System.out.println(a + b);// 7
System.out.println(a - b);// -1
System.out.println(a * b);// 12
System.out.println(a / b);// 计算机结果是0,为什么不是0.75呢?因为只取整数
System.out.println(a % b);// 3
//⭐如果在取模的运算中有负号,结果与被模数符号相同
System.out.println(5%2);//1
System.out.println(5%-2);//1
System.out.println(-5%2);//-1
System.out.println(-5%-2);//-1
//商*除数 + 余数 = 被除数
//5%-2 ==>商是-2,余数时1 (-2)*(-2)+1 = 5
//-5%2 ==>商是-2,余数是-1 (-2)*2+(-1) = -4-1=-5
}
}
-
“+” 号的两种用法
-
第一种:对于
+
两边都是数值的话,+
就是加法的意思 -
第二种:对于
+
两边至少有一边是字符串的话,+
就是拼接的意思
-
-
自加自减运算
理解:
++
运算,表示自增1
。同理,--
运算,表示自减1
,用法与++ 一致。- 单独使用
- 变量在单独运算的时候,变量
前++
和变量后++
,是没有区别的。 - 变量
前++
:例如++a
。 - 变量
后++
:例如a++
。
- 复合使用
- 和
其他变量放在一起使用
或者和输出语句放在一起使用
,前++
和后++
就产生了不同。
- 变量
前++
:变量先自增1,然后再运算。 - 变量
后++
:变量先运算,然后再自增1。
思考:++1,与s+1的区别?
解答:a = ++1,在赋值后不改变 a 的数据类型;a = s + 1,在赋值后若 a 为字节型变量,将会变为 int 型变量
5.2 赋值运算符
知识:
-
符号:=
- 当“=”两侧数据类型不一致时,可以使用自动类型转换或使用强制类型转换原则进行处理。
- 支持
连续赋值
。
-
扩展赋值运算符: +=、 -=、*=、 /=、%=
赋值运算符 符号解释 +=
将符号 左边的值
和右边的值
进行相加
操作,最后将结果赋值给左边的变量
-=
将符号 左边的值
和右边的值
进行相减
操作,最后将结果赋值给左边的变量
*=
将符号 左边的值
和右边的值
进行相乘
操作,最后将结果赋值给左边的变量
/=
将符号 左边的值
和右边的值
进行相除
操作,最后将结果赋值给左边的变量
%=
将符号 左边的值
和右边的值
进行取余
操作,最后将结果赋值给左边的变量
public class SetValueTest1 {
public static void main(String[] args) {
int i1 = 10;
long l1 = i1; //自动类型转换
byte bb1 = (byte)i1; //强制类型转换
int i2 = i1;
//赋值的写法
//写法1
int a1 = 10;
int b1 = 10;
//写法2
int a2,b2;
a2 = b2 = 10;
//写法3
int a3 = 10,b3 = 20;
//举例说明+= -= *= /= %=
int m1 = 10;
m1 += 5; //类似于 m1 = m1 + 5的操作,但不等同于。
System.out.println(m1);//15
//练习1:开发中,如何实现一个变量+2的操作呢?
// += 的操作不会改变变量本身的数据类型。其他拓展的运算符也如此。
//写法1:推荐
short s1 = 10;
s1 += 2; //编译通过,因为在得到int类型的结果后,JVM自动完成一步强制类型转换,将int类型强转成short
System.out.println(s1);//12
//写法2:
short s2 = 10;
//s2 = s2 + 2;//编译报错,因为将int类型的结果赋值给short类型的变量s时,可能损失精度
s2 = (short)(s2 + 2);
System.out.println(s2);
//练习2:开发中,如何实现一个变量+1的操作呢?
//写法1:推荐
int num1 = 10;
num1++;
System.out.println(num1);
//写法2:
int num2 = 10;
num2 += 1;
System.out.println(num2);
//写法3:
int num3 = 10;
num3 = num3 + 1;
System.out.println(num3);
}
}
思考:byte m;m += 5; 这样的操作自带了强制类型转换,即将 m+5 的 int 型强制转换为 byte 型
5.3 比较运算符
知识:
-
比较运算符的结果都是boolean型,也就是要么是true,要么是false。
-
> < >= <= :只适用于基本数据类型(除boolean类型之外)
== != :适用于基本数据类型(包含Boolean类型)和引用数据类型
-
instanceof 检查是否为类的对象
class CompareTest {
public static void main(String[] args) {
int i1 = 10;
int i2 = 20;
System.out.println(i1 == i2);//输出false
System.out.println(i1 != i2);//输出true
System.out.println(i1 >= i2);//输出false
int m = 10;
int n = 20;
System.out.println(m == n);//输出false
System.out.println(m = n);//输出20
boolean b1 = false;
boolean b2 = true;
System.out.println(b1 == b2);//输出false
System.out.println(b1 = b2);//输出true
}
}
思考:区分好 == 和 = 的区别,== 是比较运算符,= 是赋值运算符
boolean b1 = false;
if(b1 == true) //if(b1 = true)
System.out.println("结果为真");
else
System.out.println("结果为假");
5.4 逻辑运算符
知识:
- 逻辑运算符,操作的都是
boolean类型
的变量或常量,而且运算得结果也是boolean类型
的值。
运算符说明:
-
& 和 &&:表示"且"关系,当符号左右两边布尔值都是true时,结果才能为true。否则,为false。
-
| 和 || :表示"或"关系,当符号两边布尔值有一边为true时,结果为true。当两边都为false时,结果为false
-
! :表示"非"关系,当变量布尔值为true时,结果为false。当变量布尔值为false时,结果为true。
-
^ :当符号左右两边布尔值不同时,结果为true。当两边布尔值相同时,结果为false。
- 理解:
异或,追求的是“异”!
- 理解:
-
区分“&”和“&&”:
-
相同点:如果符号左边是true,则二者都执行符号右边的操作
-
不同点:& : 如果符号左边是false,则继续执行符号右边的操作
&& :如果符号左边是false,则不再继续执行符号右边的操作
发生逻辑短路
-
建议:开发中,推荐使用 &&
-
-
区分“|”和“||”:
-
相同点:如果符号左边是false,则二者都执行符号右边的操作
-
不同点:| : 如果符号左边是true,则继续执行符号右边的操作
|| :如果符号左边是true,则不再继续执行符号右边的操作
发生逻辑短路
-
建议:开发中,推荐使用 ||
-
代码举例:
public class LoginTest {
public static void main(String[] args) {
int a = 3;
int b = 4;
int c = 5;
// & 与,且;有false则false
System.out.println((a > b) & (a > c));
System.out.println((a > b) & (a < c));
System.out.println((a < b) & (a > c));
System.out.println((a < b) & (a < c));
System.out.println("===============");
// | 或;有true则true
System.out.println((a > b) | (a > c));
System.out.println((a > b) | (a < c));
System.out.println((a < b) | (a > c));
System.out.println((a < b) | (a < c));
System.out.println("===============");
// ^ 异或;相同为false,不同为true
System.out.println((a > b) ^ (a > c));
System.out.println((a > b) ^ (a < c));
System.out.println((a < b) ^ (a > c));
System.out.println((a < b) ^ (a < c));
System.out.println("===============");
// ! 非;非false则true,非true则false
System.out.println(!false);
System.out.println(!true);
//&和&&的区别
System.out.println((a > b) & (a++ > c));
System.out.println("a = " + a);
System.out.println((a > b) && (a++ > c));
System.out.println("a = " + a);
System.out.println((a == b) && (a++ > c));
System.out.println("a = " + a);
//|和||的区别
System.out.println((a > b) | (a++ > c));
System.out.println("a = " + a);
System.out.println((a > b) || (a++ > c));
System.out.println("a = " + a);
System.out.println((a == b) || (a++ > c));
System.out.println("a = " + a);
}
}
思考:区分“&”和“&&”;区分“|”和“||”,小心逻辑短路
5.5 位运算符
知识:
⭐位运算符的运算过程都是基于二进制的补码运算,结果用原码表示。
对于数值型数据类型,正数的补码为其本身(原码),负数需要取反码并加1为补码。
(1)左移:<<
运算规则:在一定范围内,数据每向左移动一位,相当于原数据*2。(正数、负数都适用)
【注意】当左移的位数n超过该数据类型的总位数时,相当于左移(n-总位数)位
3<<4 类似于 3*2的4次幂 => 3*16 => 48
-3<<4 类似于 -3*2的4次幂 => -3*16 => -48
-3的原码:1000 0000 0000 0000 0000 0000 0000 0011
反码:1111 1111 1111 1111 1111 1111 1111 1100
补码:1111 1111 1111 1111 1111 1111 1111 1101
将补码左移4位:1111 1111 1111 1111 1111 1111 1101 0000 (新的补码)
反码:1111 1111 1111 1111 1111 1111 1100 1111
原码:1000 0000 0000 0000 0000 0000 0011 0000 表示2^5+2^4=-48
(2)右移:>>
运算规则:在一定范围内,数据每向右移动一位,相当于原数据/2。(正数、负数都适用)
【注意】如果不能整除,向下取整
,向下,例如 -6.4 向下取整结果为 -7
69>>4 类似于 69/2的4次 = 69/16 =4
-69>>4 类似于 -69/2的4次 = -69/16 = -5
(3)无符号右移:>>>
运算规则:往右移动后,左边空出来的位直接补0。(正数、负数都适用)
69>>>4 类似于 69/2的4次 = 69/16 =4
-69>>>4 结果:268435451
(4)按位与:&
运算规则:对应位都是1才为1,否则为0。
- 1 & 1 结果为1,1 & 0 结果为0,0 & 1 结果为0,0 & 0 结果为0
9 & 7 = 1
9:0000 1001
7:0000 0111
与:0000 0001 结果为1
-9 & 7 = 7
-9 原码:1000 0000 0000 0000 0000 0000 0000 1001
反码:1111 1111 1111 1111 1111 1111 1111 0110
补码:1111 1111 1111 1111 1111 1111 1111 0111
7 原码:0000 0000 0000 0000 0000 0000 0000 0111
相与:0000 0000 0000 0000 0000 0000 0000 0111 结果为7
(5)按位或:|
运算规则:对应位只要有1即为1,否则为0。
- 1 | 1 结果为1,1 | 0 结果为1,0 | 1 结果为1,0 & 0 结果为0
9 | 7 //结果: 15
-9 | 7 //结果: -9
(6)按位异或:^
运算规则:对应位一个为1一个为0,才为1,否则为0。
- 1 ^ 1 结果为0,1 ^ 0 结果为1,0 ^ 1 结果为1,0 ^ 0 结果为0
9 ^ 7 //结果为14
-9 ^ 7 //结果为-16
(7)按位取反:~
运算规则:对应位为1,则结果为0;对应位为0,则结果为1。
- ~0就是1 ,~1就是0
~9 //结果:-10
~-9 //结果:8
思考: 负数采用补码运算,采用原码表示
5.6 条件运算符
知识:
- 条件运算符格式:
(条件表达式)? 表达式1:表达式2
-
说明:条件表达式是 boolean 类型的结果,根据 boolean 的值选择表达式1或表达式2
-
注意:如果运算后的结果赋给新的变量,要求 表达式1 和 表达式2 为 同种 或 兼容 的类型
public static void main(String[] args) {
int i = (1==2 ? 100 : 200);
System.out.println(i);//200
boolean marry = false;
System.out.println(marry ? "已婚" : "未婚" );
double d1 = (m1 > m2)? 1 : 2.0;
System.out.println(d1);
int num = 12;
System.out.println(num > 0 ? true : "num非正数");
}
案例1:获取两个数中的较大值
public class ConditionExer1 {
public static void main(String[] args) {
//获取两个数的较大值
int m1 = 10;
int m2 = 20;
int max1 = (m1 > m2)? m1 : m2;
System.out.println("m1和m2中的较大值为" + max1);
}
}
案例2:获取三个数中的最大值
public class ConditionExer2 {
public static void main(String[] args) {
int n1 = 23;
int n2 = 13;
int n3 = 33;
int tempMax = (n1 > n2)? n1:n2;
int finalMax = (tempMax > n3)? tempMax : n3;
System.out.println("三个数中最大值为:" + finalMax);
}
}
案例3:今天是周2,10天以后是周几?
要求:控制台输出"今天是周2,10天以后是周x"。
public class ConditionExer3 {
public static void main(String[] args) {
int week = 2;
week += 10;
week %= 7;
System.out.println("今天是周2,10天以后是周" + (week == 0 ? "日" : week));
//这里不进行赋值,允许 "日" 与 week 数据类型不同
}
}
-
与if-else的转换关系
-
凡是可以使用条件运算符的地方,都可以改写为if-else结构。反之,不成立。因为if-else结构复杂性更高。
-
开发中,如果既可以使用条件运算符,又可以使用if-else,推荐使用条件运算符。因为执行效率稍高。
-
5.7 运算符优先级
运算符有不同的优先级,所谓优先级就是在表达式运算中的运算符顺序。
上一行中的运算符总是优先于下一行的。
优先级 | 运算符说明 | Java运算符 |
---|---|---|
1 | 括号 | () 、[] 、{} |
2 | 正负号 | + 、- |
3 | 单元运算符 | ++ 、-- 、~ 、! |
4 | 乘法、除法、求余 | * 、/ 、% |
5 | 加法、减法 | + 、- |
6 | 移位运算符 | << 、>> 、>>> |
7 | 关系运算符 | < 、<= 、>= 、> 、instanceof |
8 | 等价运算符 | == 、!= |
9 | 按位与 | & |
10 | 按位异或 | ^ |
11 | 按位或 | ` |
12 | 条件与 | && |
13 | 条件或 | ` |
14 | 三元运算符 | ? : |
15 | 赋值运算符 | = 、+= 、-= 、*= 、/= 、%= |
16 | 位赋值运算符 | &= 、` |
开发建议:
- 不要过多的依赖运算的优先级来控制表达式的执行顺序,这样可读性太差,尽量使用
( )
来控制表达式的执行顺序。- 不要把一个表达式写得过于复杂,如果一个表达式过于复杂,则把它
分成几步
来完成。例如:
(num1 + num2) * 2 > num3 && num2 > num3 ? num3 : num1 + num2;