算术运算符

加 减 乘 除 取余

取模运算,余数的符号跟被除数符号相同

  1. public static void main(String[] args) {
  2. System.out.println(10 / 4); // 2 注意除法计算结果,因为都为整数,所以结果2.5会取整
  3. System.out.println(10.0 / 4); //2.5
  4. double d = 10 / 4;
  5. System.out.println(d); // 2.0
  6. }
  1. @Test
  2. public void test_9() {
  3. System.out.println(5 % 2); //1
  4. System.out.println(5.0 % 2); //1.0 求余运算也会类型提升
  5. System.out.println(-5 % 2); //-1 结果的符号和被除数的符号一致
  6. //公式: a%b = a-a/b *b =》 -5%2 = -5-(-5)/2*2 = -5 -(-2)*2 = -5 + 4 = -1
  7. System.out.println(5 % -2); //1
  8. System.out.println(-5 % -2); //-1
  9. }
  1. public class Test17 {
  2. public static void main(String args[]) {
  3. int x = -5;
  4. int y = -12;
  5. System.out.println(y % x); // -2 取模运算,余数的符号跟被除数符号相同
  6. //无论是正数还是负数,在取余运算时都有:
  7. //被除数=商×除数+余数,所以-12=2×(-5)+(-2),-12是被除数,-5是除数,2是商,余数是-2。
  8. }
  9. }

自增自减

n++ ,++n,n—,—n

  1. @Test
  2. public void test_9() {
  3. int a = 5;
  4. int b = a++; //先赋值后自增自减
  5. System.out.println(a); //6
  6. System.out.println(b); //5
  7. int a1 = 5;
  8. System.out.println(a1++); //5
  9. }
  1. @Test
  2. public void test_9() {
  3. int a = 5;
  4. int b = ++a; //先自增自减后赋值
  5. System.out.println(a); //6
  6. System.out.println(b); //6
  7. int a1 = 5;
  8. System.out.println(++a1); //6
  9. }
  1. public static void main(String[] args) {
  2. int i = 1;
  3. i = i++; // temp =i; i=i+1; i=temp
  4. System.out.println(i); //1
  5. int j = 1;
  6. j = ++j; // j=j+1; temp=j; j=temp
  7. System.out.println(j);//2
  8. }
  1. //https://www.bilibili.com/video/BV1xt411S7xy
  2. public static void main(String[] args) {
  3. int i = 1;
  4. i = i++; // i =1
  5. int j = i++; //j=1, i=2
  6. int k = i + ++i * i++; // 2 + 3 * 3
  7. System.out.println("i=" + i);
  8. System.out.println("j=" + j);
  9. System.out.println("k=" + k);
  10. }

关系运算符

大于> 大于等于>= 小于< 小于等于<= 等于== 不等于!=
关系运算符的运行结果是布尔值。

逻辑运算符

&& 与 ||或 !非
操作数只能是布尔值。

& (和 | 是位运算,可以进行逻辑运算。
&& 短路与, & 逻辑与。

区别:逻辑运算符有短路效果,位运算符不具有短路效果。

  • 单个的逻辑运算符会将左右两个表达式都进行运算得出布尔值,再进行运算。
  • ‘短路与’&& 若左边表达式为false则不会对右边的表达式进行判断,因为结果必为false;
  • ‘短路或’|| 若左边表达式结果为true则不会对右边的表达式进行判断,因为结果必为true。

运算符 - 图1

  1. public class Test13 {
  2. private static int j = 0;
  3. private static Boolean methodB(int k) {
  4. j += k;
  5. return true;
  6. }
  7. public static void methodA(int i) {
  8. boolean b;
  9. // 对于boolean值,按位操作与逻辑操作有相同的结果,但是不会发生“短路”。
  10. b = i < 10 | methodB(4); //不会编译错误,这里是给b赋值,而不是访问b
  11. b = i < 10 || methodB(8); //短路或 || 如果结果确定,不继续计算
  12. }
  13. public static void main(String args[]) {
  14. methodA(0);
  15. System.out.println(j); //4
  16. }
  17. }

扩展赋值运算符

+= -+ = /= %=
例如:a+=b ==> a = a +b
*注意:扩展运算法会有隐式强转

  1. @Test
  2. public void test_9() {
  3. short n = 5; // 因为5在short的范围内,不会报错
  4. n = n + 3; //编译报错, int转short
  5. System.out.println(n);
  6. }
  7. @Test
  8. public void test_9() {
  9. short n = 5; // 因为5在short的范围内,不会报错
  10. n += 3; //这里会有一个隐式强转 (short)(n+3)
  11. System.out.println(n);
  12. }

条件运算符

表达式一 ? 表达式二 : 表达式三
表达式一运算的结果是布尔值
表达式二和表达式三要求 类型相符
表达式一的结果为true,就执行表达式二
表达式一的结果为false,就执行表达式三

  1. @Test
  2. public void test_9() {
  3. Object object = true ? "" : new Object(); //其实这样也可以
  4. double v = true ? 2 : 2.2;
  5. //int v2 = true ? 2 : 2.2; //编译报错,2.2不能自动转为int
  6. }

位运算符

与& 或 | 非~ 异或 ^ 左移<< 右移>> 无符号右移>>>

按位运算符

  • & 按位与 规则:两个同为1的时候才为1。
  • | 按位或 规则:两个只要有一个为1就为1。
  • ^ 按位异或 规则:如果a、b两个值不相同,则异或结果为1。如果a、b两个值相同,异或结果为0。
  • ~ 取反 规则:1 变0, 0变1 (单目运算符)
  • 右移 规则:让操作数除以2的n次幂,n就是移动的位数,左边空出的位置用符号位的值补全

  • << 左移 规则:让操作数乘以2的n次幂,n就是移动的位数
  • 无符号右移 规则:让操作数除以2的n次幂,n就是移动的位数, 左边空出的位置用0补齐

在进行位运算的时候要把数据转换成二进制位,并且全部都是二进制的补码形式

~ 取反

对3进行取反位运算:~3
3是正数,原码、反码、补码是一样的。
3的补码: 0b00000000 00000000 00000000 00000011
取反~3: 0b11111111 11111111 11111111 11111100 (此时是补码,补码是原码取反加1来的,现在是减1取反)
求原码-1:0b11111111 11111111 11111111 11111011 (求原码取反的时候,符号位不需要取反)
求原码取反:0b10000000 00000000 00000000 00000100 (此时是原码) -4 给人类显示的是原码

  1. @Test
  2. public void test_8() {
  3. System.out.println(~3); //-4
  4. }

^ 按位异或

一个数据对相同的数据异或两次其值不变。
a^b^b = a

  1. @Test
  2. public void test_8() {
  3. int a =3;
  4. int b =4;
  5. System.out.println(a^b^b); //3
  6. }

通过异或实现两个变量交换,不需要第三个变量

  1. @Test
  2. public void test_8() {
  3. //一个数据对相同的数据异或两次其值不变。
  4. /*
  5. a = a ^ b;
  6. b = a ^ b; => a^b^b的结果就是a, 此时把a的值赋给b
  7. a = a ^ b; => a^b^a(因为现在的b其实是a)的结果就是b, 此时把b的值赋给a
  8. => a^b^a^b^b => a^a^b => b
  9. */
  10. int i = 10;
  11. int j = 20;
  12. i = i ^ j;
  13. j = i ^ j;
  14. i = i ^ j;
  15. System.out.println(i); //20
  16. System.out.println(j); //10
  17. }

>> 和 <<

往左移动两位,右边就空出两位,左边移动的两位就被挤掉了,右边空出的两位用0补全;
往右移动两位,左边就空出两位,右边的两位就被挤掉了,左边空出的两位用符号位的值填充(符号位是1就填充1,是0就填充0);

  1. @Test
  2. public void test_9() {
  3. int i = 3<<4; // 3*2^4
  4. System.out.println(i); //48
  5. int j = 3>>4; // 3/2^4
  6. System.out.println(j); //0
  7. int k = 35>>4; // 35/2^4
  8. System.out.println(k); //2
  9. int l = -35>>4; // 35/2^4
  10. System.out.println(l); //-3
  11. }

-35的原码:10000000 00000000 00000000 00100011
-35的反码:11111111 11111111 11111111 11011100
-35的补码:11111111 11111111 11111111 11011101
-35的补码右移4位:1111 11111111 11111111 11111111 1101
减1: 1111 11111111 11111111 11111111 1100
取反:1000 00000000 00000000 00000000 0011

>>> 无符号右移

往右移动两位,左边就空出两位,右边的两位就被挤掉了,左边空出的两位用0填充。
对于正数,>> 和 >>>的结果是一样的。
对于负数,>> 和 >>>的结果是不一样的, >>>会变为正数。

  1. public void test_9() {
  2. int k = 35>>>4; // 35/2^4
  3. System.out.println(k); //2
  4. int l = -35>>>4; // 35/2^4
  5. System.out.println(l); //268435453
  6. System.out.println(0b00001111111111111111111111111101); //268435453
  7. }

-35的原码:10000000 00000000 00000000 00100011
-35的反码:11111111 11111111 11111111 11011100
-35的补码:11111111 11111111 11111111 11011101
-35的补码右移4位:0000 11111111 11111111 11111111 1101 (此时是补码,但是是正数,原码和补码一样)