Java菜鸟学习之路---算术运算符、赋值运算符、比较运算符、逻辑运算符、位运算符、三元运算符、运算符的优先级详解(三)
程序员文章站
2022-05-18 15:59:20
...
运算符
-
定义:运算符是一种特殊得符号,用以表示数据得运算、赋值和比较等。
-
分类:算术运算符、赋值运算符、比较运算符(关系运算符)、逻辑运算符、位运算符、三元运算符
1.1算术运算符:
算术运算符得测试用例:
/*运算符:
* + - * % (前)++ (后)++ (前)-- (后)-- +(拼接运算)
* */
public class Ari_Test {
public static void main(String[] args) {
// / 除号运算(数学运算中取商)
int num = 14;
int num1 = 4;
int result = num / num1;
//做除法运算时,两整型做除法运算,结果取整,舍弃小数点,不进行进位操作
double result1 = num / num1; //输出2.0,当想得到除法精确得数值得时候,我们可能会想到用一个double数据类型得结果来接收结果,但是实际上只是将结果转换成了double型,实际运算结果值不变
double result2 = num / num1 + 0.0; //输出2.0
double result3 = num / (num1 + 0.0); //输出精确结果2.4,括号运算符里面得算术运算首先进行,num1 + 0.0,运用自动类型提升规则,int + double = double,int / double = 精准double数值
double result4 = (double) num / num1; //输出精确结果2.4,和上面原理相同,精确把握自动类型提升运算本质
System.out.println(result);
// % 取模运算(数学运算种取余运算)
//取模结果与被除数符号一致
//开发中,常使用%来进行判断,判断某数能否被除尽(余数位0)
int m1 = 12;
int n1 = 5;
System.out.println("m1 % n1 =" +m1 % n1); //2
int m2 = -12;
int n2 = 5;
System.out.println("m2 % n2 =" +m2 % n2); //-2
int m3 = 12;
int n3 = -5;
System.out.println("m3 % n3 =" +m3 % n3); //2
int m4 = -12;
int n4 = -5;
System.out.println("m4 % n4 =" +m4 % n4); //-2
//(前)++ 先自增1,后调用进行运算 (两者都表示自增1)
//(后)++ 先调用直接参与运算,后自增1
int a1 = 10;
int b1 = ++a1; //a1先++之后为11,再赋值给变量b1
System.out.println(a1); //11
System.out.println(b1); //11
int a2 = 10;
int b2 = a2++; //先调用a2,先直接赋值给b2之后,才进行了a2得自增操作
System.out.println(a2); //11,此时已自增完成后,a2得值变成了11
System.out.println(b2); //10
//注意点:
short s = 10;
//s = s + 1; 编译失败,char、byte、short任意之间两两运算或者与整型常量进行运算,结果都是int型得,不能用short型来接收结果
//s = (short)(s + 1) 正确得,int->short,大容量数据转向小容量数据,运算强制类型转换符,进行强制类型转换
s++;
//自增1,不会改变原数据本身得数据类型,这种用法效率更高,不需要进行强转截断操作
//(前)-- 先自减1,后调用进行运算 (两者都表示自减1)
//(后)-- 先调用直接参与运算,后自减1
int o1 = 10;
int p1 = --o1;
System.out.println("o1 = "+ o1 +" p1 = "+ p1); //9,9
int o2 = 10;
int p2 = o2--;
System.out.println("o2 = "+ o2 +" p2 = "+ p2); //9,10
}
}
1.2赋值运算符
赋值运算符测试用例:
/*算数运算符:赋值运算符号"="
* = += -= /= %=
*
*
* */
public class SetValue_Test {
public static void main(String[] args) {
int j1,j2; //连续定义变量
j1 = j2 = 10; //连续从右向左赋值
int j3 = 20,j4 = 20; //连续单一赋值
//******************>
int num = 6;
num += 2; //等效于num = num + 2;
System.out.println(num); //8
int num1 = 5;
num1 %= 2; //等效于num1 = num1 % 2;
System.out.println(num1); //1
//注意:上述运算符除了单个赋值运算符之外,剩下得双层赋值运算符,运算前后都不会改变变量本身得数据类型
short num2 = 8;
//num2 = num + 2; 编译不通过,short + int = int,需要进行类型提升,使用int型数据类型变量来接收结果
num2 += 2; //等效于num2 = num2 + 2;
System.out.println(num2); //10
//开发中,如果要希望变量实现+2得操作,有几种方法?(前提 : int num = 10;)
//方式1:num = num + 2;
//方式2:num += 2;(推荐)此种赋值方式不仅赋值前后不会改变数据类型,并且在数据类型为byte、short、char数据类型得时候,不会造成强转,造成精度损失得情况,并且代码量也比较少
//练习1
int num3 = 1;
num3 *= 0.1; //0,在这里首先会想到0.1是一个浮点型,然后想尝试结果也转变成浮点型,但是这样得思路错了,上面说过类似于这样得双层运算符在赋值运算前后不会改变变量本身得数据类型,所以1 * 0.1 = 0.1,对double型数据0.1进行截断操作为int型结果,得到结果为0
System.out.println(num3); //0
num3++;
System.out.println(num3); //1
//练习2
int m = 2;
int n = 3;
n *= m++; //注意把握后++,要点先调用,然后在进行自增操作,这里就是先直接调用m进行 n *= m得运算,得出n = 6,然后在进行m++运算,m=3
System.out.println("m = " + m); //3
System.out.println("n = " + n); //6
//练习3
int n1 = 10;
n1 += (n1++) + (++n1); //理解1:首先要把握n1 += ?运算符,等效于n1 = n1 + ?。那么我们肯定首先要算出右边得?得值为多少,才能向左在进行赋值得运算,接下来把握(前)++和(后)++得区别,可以算出? = 10 + 11 = 21;那么可以算出整体得n1 += 21;n1 = 31;但是别遗忘了刚才后++得自增1操作,那么n1进行自增操作后就变成了32
//理解2:n1 = n1 + (n1++) + (++n1);第一个n1++,调用时n1为10,但调用完之后实际上n1已经变成了11,那么之后得++n1操做也是在n1得基础上进行运算得,那么++n1之后,n1得值已经变成了12了
// 10 10 12
System.out.println(n1); //32
}
}
1.3比较运算符
比较运算符得测试用例:
/*算数运算符之三:比较运算符
* == != > < >= <= instanceof(判断某个对象是否是一个类得实例)
*
* 结论:
* 1.比较运算符得运算结果都是布尔boolean类型得数值,true或者false
* 2.区分"=="和"="
* */
public class Comparable_Test {
public static void main(String[] args) {
int i = 10;
int j = 20;
System.out.println(i == j); //false,"=="为比较运算符,基本数据类型比较得是两个数值得值是否相等,引用数据类型比较得是两对象变量得首地址,判断结果为true或者false
System.out.println(i = j); //20,单个"="号代表得是赋值运算符,从右向左进行运算,代表得是将赋值运算符右边得值赋给左边得变量,会对该变量原先存储得值进行覆盖
}
}
1.4逻辑运算符
逻辑运算符的测试用例:
/*运算符之四:逻辑运算符
* & && | || ! ^
* 说明:
* 1.逻辑运算符操作的都是布尔boolean类型的变量
* */
public class LogicTest {
public static void main(String[] args) {
//区分 & 和 &&
//相同点1:& 和 &&运算结果相同
//相同点2:当符号左边都是true的时候,二者都会执行符号右边的运算
//不同点:当符号左边是false时,&继续执行符号右边的操作
// 当符号左边是false时,&&不再执行符号右边的操作
//开发中,推荐使用&&
boolean b = false;
int num = 10;
if(b & (num++ > 0)) {
System.out.println("A");
}else {
System.out.println("B"); //B
}
System.out.println(num); //11
boolean b1 = false;
int num1 = 10;
if(b1 && (num1++ > 0)) {
System.out.println("A");
}else {
System.out.println("B"); //B
}
System.out.println(num1); //10
//区分: | 和 || 与 & 和 &&运算规则相同
//相同点1:| 和 ||的运算结果都是相同的
//相同点2:当符号左边都是false,两者右边的运算都会执行
//不同点:当符号左边是true的话,|右边还是会继续执行的
// 当符号左边是true的话,||右边就不会继续执行了
//开发中,推荐使用||
boolean b2 = true;
int num2 = 10;
if(b | (num2++ > 0)) {
System.out.println("A"); //A
}else {
System.out.println("B");
}
System.out.println(num2); //11
int num3 = 10;
if(b || (num++ > 0)) {
System.out.println("A"); //A
}else {
System.out.println("B");
}
System.out.println(num3); //10
}
}
1.5位运算符
-
结论
(1)位运算符操作的都是整型的数据
(2)位运算符进行的操作都是在二进制数的基础上进行的(移动位数不能过大,否则超过了数据类型的范围的话,数值会变成负数)
经典面试题:最高效的方式计算2 * 8?
2 << 3 或 8 << 1
例:十进制的21转换成二进制数位(0001 0101)
21 << 2:0101 0100 结果为84。在一定范围内,左移几位就相当于在原数的基础上 * 2^移动位数倍。
21 >> 1:0000 1010 结果为10。在一定范围内,右移几位就相当于在原数的基础上 / 2^移动位数倍。
例:求~9
9得补码:01001(正数得原码、反码和补码都是相同得)
对9得补码取反,得到~9得补码:10110
~9(负数)得反码为:补码 - 1,反码为:10101
~9(负数)得原码为:反码符号位不变,各位取反,原码为11010
二进制数转~9换成十进制数得到~9为-10
例:求~-6
-6得原码为:1110
-6得反码为:1001
-6得补码为:1010
对-6得补码取反,得到~-6得补码:0101
所以,~-6得原码为0101(正数得原码 = 反码 = 补码)
二进制数转~-6换成十进制数得到~-6为5
-
结论:正数取反,结果为十进制正数取反 - 1(~9 = - 9 - 1 = -10 )
负数取反,结果为十进制负数取反 - 1(~-6 = 6 - 1 = 5)
1.6三元运算符
三元运算符的测试用例:
/*运算符之六:三元运算符
* 1.结构:(条件表达式)?表达式1:表达式2;
* 2.说明:
* (1)条件表达式的结果为布尔boolean类型数值
* (2)根据条件表达式的真或假,来判断执行的表达式为表达式1还是表达式2
* 条件表达式结果为真(true)时,表达式1的值就是需要的值,执行表达式1
* 条件表达式结果为假(false)时,表达式2的值就是需要的值,执行表达式2
* (3)表达式1和表达式2是一致的。
* (4)三元运算符是可以嵌套的
* 3.凡是可以使用三元运算符的地方,都可以改写成if-else语句
* 反之,不成立。
* 4.如果条件判断语句既可以使用三元运算符,if-else语句来写的话,优先推荐使用三元运算符
* 因为三元运算符执行效率更高,更简洁。
* */
public class SanYuan_Test {
public static void main(String[] args) {
//获取两个正整数的较大值
int m = 12;
int n = 5;
int max = m > n?m : n;
System.out.println(max); //12
//int max = m > n?2 : 1.0; 编译出错,三元运算符在进行赋值运算之前,表达式1和表达式2的值会进行数据类型比较,较小容量数据会自动向较大容量数据进行自动类型提升
double max1 = m > n?2 : 1.0; //所以,运算结果,也需要用较大容量的数据类型变量来接收
//*************************************
String maxStr = m > n?"m大":(m == n)?"m和n一样大":"n大";
System.out.println(maxStr); //m大
//*************************************
//获取三个数的最大值
int n1 = 15;
int n2 = 66;
int n3 = -36;
int max2 = n1 > n2?n1 : n2;
int max3 = max2 > n3?max2 : n3;
System.out.println(max3); //66
//不建议这样使用,可读性差,效率低。
int max4 = n1 > n2?(n1 > n3?n1 : n3):n2;
System.out.println(max4); //66
}
}
1.7运算符的优先级