Java的算数运算符、关系运算符、逻辑运算符、位运算符

r囧r小猫 2024-03-26 18:35 173阅读 0赞

JAVA的运算符,分为四类:
算数运算符、关系运算符、逻辑运算符、位运算符
章节一 算数运算符(7)

加(+)、减(-)、乘 (*)、除 (/)、 取余(%)、 加加(++)、 减减(–)、

章节二 赋值运算符

赋值(=)、加等(+=)、减等(-=)、乘等(*=)、除等(/=),取余等(%=)

章节三 关系运算符(6)

相等(==)、不相等 (!=)、 大于(>)、 大于等于(>=)、 小于(<) 、小于等于(<=)

章节四 条件运算符(1)

三元运算符
条件 ? 表达式1 : 表达式2
当条件成立时,执行表达式1,不成立则执行表达式2

章节五 逻辑运算符(6)

短路与(&&)、短路或(||)、取否(!)、逻辑异或(^) 、逻辑与(&)、 逻辑或(|)

章节六 位运算符(7)

位与(&),位或(|),位非(~),位异或(^),右移(>>),左移(<<),无符号右移运算符[0填充的右移] (>>>)

章节七 Java运算符优先级


第一章节 算数运算符

算数运算符操作数必须是数值类型。分为一元运算符和二元运算符;
一元运算符:只有一个操作数;
二元运算符:有两个操作数,运算符在两个操作数之间。

一元运算符:正‘+’,负‘-’,自加‘++’,自减–‘这四个。
①”++“和”–“运算符,只允许用于数值类型的变量,不允许用于表达式中;
“++”和”–“可以用于数值变量之前或者之后;

两处使用差别:

(1)”++“和”–“用于数值变量之前,在赋值操作中,先对被”++“或”–“操作变量值先加1或者先减1,然后在进行其他的操作;
例如++i是先将i的值加1后,然后在进行其它的操作

(2)”++”和”–“用于数值变量之后,在赋值操作中,先用被”++“或”–“的操作变量值进行其他的操作,然后在对其值加1或者减1。
例如i++是先进行其它的操作,然后在将i的值加1。

案例1:

  1. public class Operator {
  2. public static void main(String[] args) {
  3. int a = 5;
  4. int b,c,d,f,g,h;
  5. b = +a; //正值
  6. System.out.println("b="+b+",a="+a);
  7. c = -a; //负值
  8. System.out.println("c="+c+",a="+a);
  9. int i = 2;
  10. d = ++i; //先i=i+1;再d=l
  11. System.out.println("d="+d+",i="+i);
  12. int m = 3;
  13. f = m++;//先f=m;再m=m+1
  14. System.out.println("f="+f+",m="+m);
  15. int n = 4;
  16. g = --n;//先n=n-1;再g=n
  17. System.out.println("g="+g+",n="+n);
  18. int o = 6;
  19. h = o--;//先h=o;再o=o-1
  20. System.out.println("h="+h+",o="+o);
  21. }
  22. }
  23. 结果:
  24. 上代码,输出结果为:
  25. b=5,a=5
  26. c=-5,a=5
  27. d=3,i=3
  28. f=3,m=4
  29. g=3,n=3
  30. h=6,o=5

注:一元运算符和前后的操作数之间有空格,可能在有些编译器下编译时会出错。

加’+’,减’-‘,乘’*’,除’/’,求余’%’
(1)在算数运算符中,”+“,”-“,”“,”/“完成加减乘除四则运算,遵守数学运算。有括号先算括号里的内容,没有括号的时候先算乘除再算加减。
(2)%是求两个操作数相除后的余数。
运算规则和数学运算基本相同,在算数运算中,计算时按照从左向右的顺序计算,乘除和求余优先于加减,不同的是,程序中的乘运算符不可省略,在数学中可写为”y=2x“而程序中必须写为”y=2
x“。

知识扩展:java中/与%的区别
/ 取商数 % 取余数

/ 读作除,%读作取余(也叫取模)。/得到的是除法运算的整数,%得到的是除法运算的商(整数)。 例如:7除3商2余1,所以7/3=2,7%3=1。

注意:
(1) 取余(取模)有个规律就是:左边小于右边,结果为左边,左边大于右边,看余数。
(2)两个整数相除结果还是整数,向下取整。只要相除中有一个小数,结果带小数。
(3)目前%(取模)常见使用场景为奇偶数的判断: x%2 ,0为偶数,1为奇数。
(4)/10 就是删除数字的个位数,%10就是返回数字的个位数

案例2:

  1. System.out.println(3/5) = 0;
  2. System.out.println(6/5) = 1;
  3. System.out.println(11/5) = 2;
  4.    结果等于得到的整数(商的整数)
  5.   结果等于余数(剩余多少
  6. System.out.println(2%5) = 2;
  7. System.out.println(7%8) = 7;
  8. System.out.println(6%8) = 6;

类型转换
当二元运算的两个操作数的数据类型不同时,运算结果的数据类型和参与运算的操作数的数据类型中精度较高(或位数较长)一致。

案例2:

  1. int a = 5;
  2. double b = 4.53;//或者3.53d
  3. float c = 2.7f;
  4. int d = 1;
  5. System.out.println("int /int :a/d="+a/d);
  6. System.out.println("double/int:b/a="+b/a);
  7. System.out.println("float/int:c/a="+c/a);
  8. 结果:
  9. int /int :a/d=5
  10. double/int:b/a=0.906
  11. float/int:c/a=0.54

转换原则:从低精度向高精度转换byte 、short、int、long、float、double
低精度到高精度会自动转换,而高精度到低精度则要类型强制转换。
案例3:

  1. int a = 7;
  2. double b = 5.33; 3
  3. b = a;
  4. a = (int) b;
  5. a=b(编译错误)

第二章节 赋值运算符

赋值运算符包括基本的赋值运算符(=)与复和赋值运算符(+=、-=、=、/=、%=)
(1) 基本赋值运算符比较简单,例如a=100指的是将整数100赋值给变量a.
(2)复合赋值是指先执行运算符指定的运算,然后再将运算结果存储到运算符左边操作数指定的变量中。
例如:
a+=100 等价于 a=a+100
a-=100 等价于 a=a-100
a
=100 等价于 a=a*100
a/=100 等价于 a=a/100
a%=100 等价于 a=a%100

下表列出了“+=、-=、*=、/=、%=”复合赋值运算符的描述及例子。

+=

复合赋值运算符“+=”,表示的意思是先将运算符左边操作数指向的变量值和右边的操作数执行相加操作,然后再将相加的结果赋值给左边的操作数指向的变量。
例如下面语句: a+=100 等价于 a=a+100

-=

复合赋值运算符“-=”,表示的意思是先将运算符左边操作数指向的变量值和右边的操作数执行相减操作,然后再将相减的结果赋值给左边的操作数指向的变量
例如下面语句:a-=100 等价于 a=a-100

*=
复合赋值运算符 “ =”,表示的意思是先将运算符左边操作数指向的变量值和右边的操作数执行相乘操作,然后再将相乘的结果赋值给左边的操作数指向的变量
例如下面语句:a
=100 等价于 a=a*100

/=

复合赋值运算符“/=”,表示的意思是先将运算符左边操作数指向的变量值和右边的操作数执行相除操作,然后再将相除的结果赋值给左边的操作数指向的变量。
例如下面语句:a/=100 等价于 a=a/100

%=

复合赋值运算符“%=”,表示的意思是先将运算符左边操作数指向的变量值和右边的操作数执行取余操作,然后再将取余的结果赋值给左边的操作数指向的变量。
例如下面语句:a%=100 等价于 a=a%100

知识扩展
在这里插入图片描述

注意:
对于++自增运算符
如果++单独使用

放在变量前面或者放在变量后面,没有区别,都是将变量的值自增1

如果++放在表达式里面使用

++在变量前面,先将变量的值自增1,再进行其他运算
++在变量后面 先取值参与运算,最后自增1

第三章节 关系运算符
关系运算符用于比较两个数值之间的大小,其运算结果为一个逻辑类型(boolean布尔类型)的数值。
等于’==’,不等于’!=’,大于’>’,大于等于’>=’,小于’<’,小于等于’<=’
案例4:

  1. System.out.println("9.5<8 :"+(9.5<8));
  2. System.out.println("8.5<=8.5:"+(8.5<=8.5));
  3. System.out.println("a~z:"+((int)'a')+"~"+((int)'z'));
  4. System.out.println("A~Z:"+((int)'A')+"~"+((int)'Z'));
  5. System.out.println("'A' < 'a':"+('A' < 'a'));//字符'A'的Unicode编码值小于字符'a'
  6. 结果:
  7. 9.5<8 :false
  8. 8.5<=8.5:true
  9. a~z97~122
  10. A~Z65~90
  11. A < a’:true

注: boolean类型只能比较相等和不相等,不能比较大小;
总结:

(1)=的意思是大于或等于,两者成立一个即可,结果为true,<=亦如此;
(2) 判断相等的符号是两个等号,而不是一个等号,这个需要特别小心。 实际代码中,数值、变量以及运算结果都可以直接参与比较,只是程序中为了增强可读性,有些时候需要将比较分开进行书写。
(3)比较运算符是程序设计中实现数据比较的基础,也是很多逻辑实现的基础,在程序逻辑中,经常通过比较一定的条件,来判断后续的程序该如何执行。

第四章节 条件运算符

条件运算符属于三目运算符,它的语法结构是:布尔表达式?表达式 1:表达式 2。它的运行原理是:先判断布尔表达式的结果是 true 还是 false,如果是 true,则选择表达式 1 的结果作为整个表达式的结果,反之则选择表达式 2 的结果作为整个表达式的结果。

来看一段代码:

  1. public class TestDemo{
  2. public static void main(String[] args) {
  3. //编译报错:这不是一个语句
  4. //10;
  5. boolean flag = true;
  6. //编译报错:这不是一个语句
  7. //flag ? 1 : 0;
  8. //以上如果是一条完整的语句应该这样写
  9. int k = flag ? 1 : 0;
  10. System.out.println("k = " + k); //1
  11. //三目运算符最经典的用法
  12. boolean sex = true;
  13. //当布尔变量 sex 为 true 则结果是'男',反之'女'
  14. char gender = sex ? '男' : '女';
  15. System.out.println("性别:" + gender); //男
  16. sex = false;
  17. gender = sex ? '男' : '女';
  18. System.out.println("性别:" + gender); //女
  19. //又如
  20. int x = 100;
  21. int y = 100;
  22. System.out.println(x==y?"x 和 y 相等":"x 和 y 不相等");
  23. }
  24. }

第五章节

逻辑运算符把各个运算的关系表达式连接起来组成一个复杂的逻辑表达式,以判断程序中的表达式是否成立,判断的结果是 true 或 false。

下表详细列举出了java中常见的java运算符
在这里插入图片描述
下表详细列举了各个操作符实际应用中的返回值
在这里插入图片描述
案例:

  1. public class TestDemo{
  2. public static void main(String[] args) {
  3. System.out.println(5 > 3 & 5 > 4); // true
  4. System.out.println(5 > 100 | 5 > 4); // true
  5. System.out.println(!(5 > 3)); // false
  6. System.out.println(!(5 < 3)); // true
  7. System.out.println(true & true); // true
  8. System.out.println(true & false); // false
  9. System.out.println(true | false); // true
  10. System.out.println(!false); // true
  11. System.out.println(!true); // false
  12. System.out.println(true ^ false); // true
  13. System.out.println(true ^ true); // false
  14. System.out.println(false ^ false); // false
  15. // 重点研究逻辑与(&)和短路与(&&)的区别
  16. int x = 100;
  17. int y = 98;
  18. int z = 99;
  19. System.out.println(x > y & x > z); //true
  20. System.out.println(x > y && x > z); //true
  21. /*
  22. 通过测试得出,逻辑与(&)和短路与(&&)最终运行
  23. 结果相同那么它们有什么区别呢?请看以下代码。
  24. */
  25. int m = 99;
  26. int n = 100;
  27. System.out.println(m > n & m > n++); //false
  28. /*
  29. 逻辑与(&)运算符只有当两边的操作数都是 true 的时候,
  30. 结果才是 true,只要有一个是 false,结果必然是 false。
  31. 以上程序逻辑左边的表达式(m > n)显然结果是 false,
  32. 通过左边的表达式已经可以得出结果是false 了,右边的
  33. 表达式没有执行的必要,那我们来看一下右边的表达式
  34. 有没有执行,只要输出 n 就可以了断定。
  35. */
  36. System.out.println("n = " + n); //101
  37. /*
  38. 以上程序的运行结果是 101,足以说明 n++已经执行了。
  39. 也说明了逻辑与运算符无论左边表达式结果是true 还
  40. 是 false,右边表达式一定会执行。
  41. */
  42. //那我们来看一下短路与(&&)是怎样的?
  43. int k = 99;
  44. int f = 100;
  45. System.out.println(k > f && k > f++); //false
  46. System.out.println("f = " + f); //100
  47. /*
  48. 通过以上测试得出 f++并没有执行,因为左边表达式(k > f)
  49. 为 false,右边的表达式就不再执行了,这种现象被称为短路
  50. 现象。也就是说对于短路与来说,左边的表达式只要为 false,
  51. 就会发生短路,右边表达式不再执行了。
  52. */
  53. }
  54. }
  55. 总结:
  56. 通过以上的测试,可以得出短路与(&&)在左边的表达式结果为 false 的时候,右边的表达式则不再执行,
  57. 这种现象被称为短路现象,这种机制也显得短路与比较智能一些,效率更高一些,所以在实际开发中
  58. 短路与(&&)的使用率要比逻辑与高一些。但这并不是绝对的,有的时候也可能会选择使用逻辑与( & ),
  59. 这取决于你是否期望右边的表达式一定执行。

下面通过一个案例理解一下逻辑与和短路与之间的区别
在这里插入图片描述
注意:
(1) 逻辑运算符操作的都是boolean类型的变量,而且结果也是boolean类型。
(2) & 与 && 的区别:& 和 | 左右两边的式子一定会执行(比较笨),&& 和 || 只要左边的式子能得出结果,右边的式子就不会执行(比较聪明)。
(3)短路与(&&)和短路或(||)能够采用最优化的计算方式,从而提高效率。在实际编程时,应该优先考虑使用短路与和短路或。
(4)& 既是位运算符又是逻辑运算符,&的两侧可以是int,也可以是boolean表达式,当&两侧是int时,要先把运算符两侧的数转化为二进制数再进行运算,而短路与(&&)的两侧要求必须是布尔表达式。
案例:

  1. 12&5 的值是多少?
  2. 答:12转成二进制数是1100(前四位省略了),5转成二进制数是0101,则运算后的结果为01004
  3. 这是两侧为数值时;

第六章节 位运算符

位运算是以二进制位为单位进行的运算,其操作数和运算结果都是整型值。
位与’&’,位或’|’,位非’~’,位异或’^’,右移’>>’,左移’<<’,无符号右移运算符[0填充的右移] ’>>>’

位运算的位与’&’,位或’|’,位非’~’,位异或’^’与逻辑运算的相应操作的真值表完全相同,其差别只是位运算操作的操作数和运算结果都是二进制整数,而逻辑运算相应操作的操作数和运算结果都是逻辑值boolean型。

下表列举了位运算的详细信息
在这里插入图片描述
下表列举了位运算的一些细节
在这里插入图片描述
在这里插入图片描述

下面的函数可以帮助我们打印Java中int整型的在底层的32位信息,后面可以使用该工具对程序进行调试:

  1. public static void print(int num) {
  2. for (int i = 31; i >= 0; i--) {
  3. System.out.print((num & (1 << i)) == 0 ? "0" : "1");
  4. }
  5. System.out.println();
  6. }
  7. // print(1); --> 00000000000000000000000000000001
  8. // print(-1); --> 11111111111111111111111111111111
  9. // print(Integer.MAX_VALUE); --> 01111111111111111111111111111111
  10. // print(Integer.MAX_VALUE); --> 10000000000000000000000000000000

下面开始全面讲解每一个操作符

  1. ^(异或运算符)
    ^是针对二进制的二目运算符。

运算规则:两个二进制数值如果在同一位上相同,则结果中该位为0,否则为1,比如1011 & 0010 = 1001。

  1. |(或运算符)
    |是针对二进制的二目运算符。

运算规则:两个二进制数值如果在同一位上至少有一个1,则结果中该位为1,否则为0,比如1011 & 0010 = 1011。

  1. &(与运算符)
    &是是针对二进制的二目运算符。

需要注意的是&&是java中判断条件之间表示“和”的标识符,&是一个二目运算符,两个二进制数值如果在同一位上都是1,则结果中该位为1,否则为0,可以认为两个都是true(1),结果也为true(1),比如1011
& 0110 = 0010。

&还有一个比较重要的地方,也是面试中经常出现的问题,即该运算符可以计算余数。我们知道四则运算中速度最慢的就是除,而取余操作更加慢,因此可以通过&来快速的求两个数的余数,来看例子:

  1. public ModTest{
  2. public static void main(String[] args){
  3. System.out.println(45 & 11);
  4. System.out.println(45 & 7);
  5. }
  6. /**result:3, 5*/
  7. }
  8. 给定x, y两个数值,想求xy的余数,只需要x & (y-1)即可,
  9. 如上面例子所示,想求4512458)的余数,只要求45 & 1145 & 7)。

案例:

  1. 位与(&)的具体运算规则为:**
  2. 1 & 1 = 1 1 & 0 = 0 0 & 1 = 0 0 & 0 = 0
  3. **按位与(&)**的具体运算规则为:
  4. 1 | 1 = 1 1 | 0 = 1 0 | 1 = 1 0 | 0 = 0
  5. // 任何数与0相或都等于自身
  6. // 任何数与自己相或都等于自己

注意:
(1)在Java中,(&)不仅可以作为位运算符号,同样也可以作为逻辑与符号,
所以(&&)并不是位运算符号,不可以参与位运算!
(2)在Java中,(|)不仅可以作为位运算符号,同样也可以作为逻辑与符号。
所以(||)并不是位运算符号,不可以参与位运算!

Java中的 << << >>> 是什么?

“<<” 表示左移,不分正负数,低位补0
“>>” 表示右移,如果该数为正,则高位补0,若为负数,则高位补1
“>>>”表示无符号右移,也叫逻辑右移,即若该数为正,则高位补0,而若该数为负数,则右移后高位同样补0

4、<<, 其中<<表示左移运算符
例如8<<2,表示将8向左移2位,结果为32。低位补0。

  1. 二进制演算:
  2. 8的二进制:1 0 0 0
  3. 向左移动两位结果为1 0 0 0 0 0,换算成十进制即为32
  4. 也可以简单的理解为,左移就是将数变大,相当于8*2^2=32

左移运算符的运算规律:将左边的数按照右边的数往左移动几位。
<<x(常数): 向左移动x位(顶点在哪个方向就往哪个方向移动),无论正负数低位(最右边)都补x个0。

5、>>,其中”>>”表示右移运算符

  1. 例如 8>>2,表示将8向右移动2位,结果为2。高位补0
  2. 二进制演算:
  3. 8的二进制:1 0 0 0
  4. 向右移动两位:0 0 1 0即为2,也可以简单的理解为将数向右移位就是将数变小,相当于8除以2^2=2

右移运算符运算规律:将左边的数按照右边的数右移几位。
. >>x(常数): 向右移动x位(顶点在哪个方向就往哪个方向移动),如果该数是正数,则高位(最左边)补x个0,如果是负数,则最高位补x个1。

6、>>> 其中”>>>”表示无符号右移运算符。高位补0
例如8>>>2表示将8向右移位2位,结果为2。这个也可以和右移运算符一起理解。

. >>> x(常数): 表示无符号右移x位,所谓无符号是与>>x对比,该操作在移动后,无论正负数高位(最左边)都补0

  1. 案例1
  2. 4. <<(左移运算符)
  3. 举例1:-20<<2
  4. 原码:10000000 00000000 00000000 00010100
  5. 反码: 11111111 11111111 11111111 11101011(符号位不变,其他位取反)
  6. 补码: 11111111 11111111 11111111 11101100(反码 + 1
  7. 左移两位(最右边两位添0
  8. 补码: 11111111 11111111 11111111 10110000
  9. 反码: 11111111 11111111 11111111 10101111(补码 - 1
  10. 原码: 10000000 00000000 00000000 01010000(符号位不变,其他位取反)
  11. 结果:-80
  12. 举例220<<2
  13. 原码(反码,补码):00000000 00000000 00000000 00010100
  14. 左移两位(最右边两位添0
  15. 原码(反码,补码):00000000 00000000 00000000 01010000
  16. 结果:80
  17. 5. >>(右移运算符)
  18. 举例1:-20>>2
  19. 原码:10000000 00000000 00000000 00010100
  20. 反码: 11111111 11111111 11111111 11101011(符号位不变,其他位取反)
  21. 补码: 11111111 11111111 11111111 11101100(反码 + 1
  22. 右移两位(最左边两位添1
  23. 补码: 11111111 11111111 11111111 11111011
  24. 反码: 11111111 11111111 11111111 11111010(补码 - 1
  25. 原码: 10000000 00000000 00000000 00000101(符号位不变,其他位取反)
  26. 结果:-5
  27. 举例220>>2
  28. 原码(反码,补码):00000000 00000000 00000000 00010100
  29. 右移两位(最左边两位添0
  30. 原码(反码,补码):00000000 00000000 00000000 00000101
  31. 结果:5
  32. 6. >>>(无符号右移运算符)
  33. 举例1:-2>>>1
  34. 原码:10000000 00000000 00000000 00000010
  35. 反码: 11111111 11111111 11111111 11111101(符号位不变,其他位取反)
  36. 补码: 11111111 11111111 11111111 11111110(反码 + 1
  37. 右移1位(无符号位运算符,最左边一位只添0
  38. 补码: 01111111 11111111 11111111 11111111
  39. 反码: 01111111 11111111 11111111 11111111(高位为0,正数)
  40. 原码: 01111111 11111111 11111111 11111111(与反码相同)
  41. 结果:2147483647
  42. 举例22>>>1
  43. 原码(反码,补码):00000000 00000000 00000000 00000010
  44. 右移一位(最左边一位添0
  45. 原码(反码,补码):00000000 00000000 00000000 00000001
  46. 结果:1
  47. 案例2
  48. System.out.println("16 <<1 : " + (16 <<1));
  49. System.out.println("16 >> 3 : " + (16 >> 3));
  50. System.out.println("16 >> 10 : " + (16 >> 10));
  51. System.out.println("1 >> 1 : " + (1 >> 1));
  52. System.out.println("16 >>> 2 : " + (16 >>> 2));
  53. System.out.println("-16 >> 2 : " + (-16 >> 2));
  54. System.out.println("-16 <<2 : " + (-16 <<2));
  55. System.out.println("-16 >>> 2 : " + (-16 >>> 2));
  56. 结果:
  57. 16 <<1 : 32
  58. 16 >> 3 : 2
  59. 16 >> 10 : 0
  60. 1 >> 1 : 0
  61. 16 >>> 2 : 4
  62. -16 >> 2 : -4
  63. -16 <<2 : -64
  64. -16 >>> 2 : 1073741820
  65. 案例3
  66. int i = 2 << 3;
  67. int j=i >> 3;
  68. System.out.println("i..."+i);
  69. System.out.println("j..."+j);
  70. int i1 = 7 << 3;
  71. int j1=i1 >> 3;
  72. System.out.println("i1..."+i1);
  73. System.out.println("j1..."+j1);
  74. int i2 = 11 << 4;
  75. int j2=i2 >> 3;
  76. System.out.println("i2..."+i2);
  77. System.out.println("j2..."+j2);
  78. 结果:
  79. i...16
  80. j...2
  81. i1...56
  82. j1...7
  83. i2...176
  84. j2...22

总结:

7 << 3(左移 3 位相当于7乘以 2 的 3 次方,即7222=56
56>>3或者( 56>>>3)右移 3 位相当于56除以 2 的 3 次方)。56/2
2*2=7

第七章节 Java运算符优先级

当多个运算符出现在一个表达式中,谁先谁后呢?这就涉及到运算符的优先级别的问题。在一个多运算符的表达式中,运算符优先级不同会导致最后得出的结果差别甚大。

例如:

  1. (1+3)+(3+2)*2,这个表达式如果按加号最优先计算,答案就是 18,如果按照乘号最优先,答案则是 14
  2. 再如,x = 7 + 3 * 2;这里x得到13,而不是20,因为乘法运算符比加法运算符有较高的优先级,
  3. 所以先计算3 * 2得到6,然后再加7

下表中具有最高优先级的运算符在的表的最上面,最低优先级的在表的底部。
在这里插入图片描述
在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,173人围观)

还没有评论,来说两句吧...

相关阅读