2631 字
13 min
0

运算符

运算符是编程语言中用于执行各种操作的符号。Java 中的运算符可分为算术运算符、比较运算符、逻辑运算符、位运算符、赋值运算符等。本文将深入探讨 Java 中各类运算符的使用及其应用场景,帮助开发者更好地理解和掌握运算符的使用方法。

算术运算符

二元运算符

  1. 二元运算符指的是需要两个操作数才能完成运算的运算符,例如:+,-,*,/,%。
  2. +号不但可以做加法运算,还可以表示正号和字符串连接符。
  3. 两个整数做除法(/)运算,结果只保留整数
public class OperatorDemo {
    public static void main(String[] args) {
        // + 作为加法运算
        int sum = 5 + 3;
        System.out.println("5 + 3 = " + sum);
 
        // + 作为正号
        int positive = +sum;
        System.out.println("+sum = " + positive);
 
        // + 作为字符串连接符
        String text = "result: " + sum;
        System.out.println(text);
 
        // 两个整数做除法
        int a = 7;
        int b = 3;
        System.out.println("7 / 3 = " + (a / b)); // 只保留整数
    }
}
 

一元运算符

  1. 只需要一个操作数的运算符称为一元运算符,如:++,- - 等。
  2. num++++num,都等价于num = num + 1
  3. ++num先自增,后参与运算;num++先参与运算,后自增。
  4. num++++num单独使用时没有区别,参与混合运算时,由于操作数栈和局部变量表的更新顺序不同,结果也不同
  1. 可以对常量进行递增或递减操作吗?例如:5++++5

    不能

    public class ConstantIncrementDemo {
        public static void main(String[] args) {
            // 错误示例:常量不能递增
            // 5++;
            // ++5;
     
            // 正确示例:变量可以递增
            int num = 5;
            num++;        // 后缀递增
            System.out.println("After num++: " + num); // 输出 6
     
            ++num;        // 前缀递增
            System.out.println("After ++num: " + num); // 输出 7
        }
    }
     
  2. int num = 5; num = num++;请问代码执行后num的值为多少?

    5

    • num++ 执行时,首先会取出 num 当前的值(即 5),并将其压入操作数栈中。此时,操作数栈中有一个值:5
    • num++ 会执行自增操作,将 num 的值加 1,变为 6。此时,栈中的 5 保持不变,而 num 的实际值已经变成了 6
    • 接下来,num = num++ 中的 num++ 会返回操作数栈中的值,即 原始值 5。这时,赋值操作 num = 5 会将 num 设置为 5,覆盖了先前自增后的值 6
    public class Main {
        public static void main(String[] args) {
            int num = 5;
            num = num++;  // 后缀自增赋值
            System.out.println(num); // 输出 5
        }
    }
                

赋值运算符

= : 将右边的值赋给左边的变量。

扩展赋值运算符

  1. 扩展赋值运算符:是算术运算符和赋值运算符的结合。
  2. 扩展赋值运算符,会对计算结果自动进行转型。
运算符用法举例等效的表达式
+=a += ba = a+b
-=a -= ba = a-b
*=a *= ba = ab
/=a /= ba = a/b
%=a %= ba = a%b

常见面试题

  1. short num = 11; num = num + 1;short num = 11; num += 1; 哪一个正确呢?

    第2个正确,由于num + 1的返回值类型是int,而扩展赋值运算符会对计算结果自动进行转型为short,而第一种方法不会自动转型,从而会导致类型不匹配。

    1756963579838

  2. int sum += 30; 请问这行语句语法是否正确?

    不正确,等价于int sum = sum + 30;,sum还未定义,不能使用。

比较运算符

比较运算符用来进行比较运算,运算结果是boolean类型。

比较运算符: >、 <、 >=、 <=、==、 !=

逻辑运算符

参与逻辑运算的数据类型必须为boolean类型,逻辑运算后的结果也为boolean类型。

与运算(&)

  1. 运算两边只要有一个为false,那么结果肯定为false。
  2. 只有运算两边都为true,那么结果才为true。

或运算(|)

  1. 运算两边只要有一个true,那么结果肯定为true。
  2. 只有运算两边都为false,那么结果才为false。

异或运算(^)

  1. 运算两边相同,那么结果肯定为false。
  2. 运算两边不同,那么结果肯定为true。

非运算(!)

  1. !true == false;
  2. !false == true;

短路与(&&)

&&&的运算结果是一样的,但是运算的过程有所不同。

  1. &:无论左边的运算结果是什么,右边都需要参与运算。
  2. &&
    • 如果左边运算结果为false,那么右边就不需要参与运算了,直接返回结果false。
    • 如果左边运算结果为true,那么需要进行右边的运算,并返回右边运算的结果。
public class Main {
    public static void main(String[] args) {
        int x = 5;
 
        // 使用 &,右边始终会执行
        boolean result1 = (x > 10) & (++x > 5);
        System.out.println("& 运算结果: " + result1);
        System.out.println("x 的值(& 后): " + x);
 
        x = 5; // 重置
 
        // 使用 &&,短路运算
        boolean result2 = (x > 10) && (++x > 5);
        System.out.println("&& 运算结果: " + result2);
        System.out.println("x 的值(&& 后): " + x);
    }
}
 

短路或(||)

|||的运算结果是一样的,但是运算的过程有所不同。

  1. |:无论左边的运算结果是什么,右边都需要参与运算。
  2. ||
    • 如果左边运算结果为true,那么右边就不需要参与运算了,直接返回结果true。
    • 如果左边运算结果为false,那么需要进行右边的运算,并返回右边运算的结果。
public class Main {
    public static void main(String[] args) {
        int x = 5;
 
        // 使用 |,右边始终会执行
        boolean result1 = (x < 10) | (++x > 5);
        System.out.println("| 运算结果: " + result1);
        System.out.println("x 的值(| 后): " + x);
 
        x = 5; // 重置
 
        // 使用 ||,短路运算
        boolean result2 = (x < 10) || (++x > 5);
        System.out.println("|| 运算结果: " + result2);
        System.out.println("x 的值(|| 后): " + x);
    }
}
 

位运算符

位运算符用于直接操作整数的二进制位。

<<左移

  1. 左移n位,等于在原数据上乘以2的n次方。
  2. 3*2可以使用 3 << 1来实现,这样做的效率更高。
  3. 左移低位补0。
public class Main {
    public static void main(String[] args) {
      	// 左移运算,8*2^2 = 32
        System.out.println("8 << 2 = " + (8 << 2));
      
      	// 左移运算,-8*2^2 = -32
        System.out.println("-8 << 2 = " + (-8 << 2));
    }
}
 

>>右移

  1. 右移n位,等于在源数据上除以2的n次方。
  2. 3/2可以使用 3 >> 1 来实现,这样做的效率更高。
  3. 正数则在高位补0,负数则在高位补1。
public class Main {
    public static void main(String[] args) {
        // 右移运算,8 / 2^2 = 2
        System.out.println("8 >> 2 = " + (8 >> 2));
 
        // 右移运算,-8 / 2^2 = -2
        System.out.println("-8 >> 2 = " + (-8 >> 2));
    }
}
 

>>>无符号右移

  1. >>> 和 >> 移动类似,但是无论值的正负,都在高位补0
  2. ⚠️ 注意:没有无符号左移,因为左移本来就没有区分符号,符号位直接被覆盖
public class Main {
    public static void main(String[] args) {
        int num1 = 8;    // 正数
        int num2 = -8;   // 负数
 
        // 原始二进制
        System.out.println("8 的二进制:          ");
        System.out.println("    " + String.format("%32s", Integer.toBinaryString(num1)).replace(' ', '0'));
        System.out.println("-8 的二进制:         ");
        System.out.println("    " + String.format("%32s", Integer.toBinaryString(num2)).replace(' ', '0'));
 
        // 左移
        int leftShift = num1 << 2;
        System.out.println("8 左移 2 位 = " + leftShift);
        System.out.println("    " + String.format("%32s", Integer.toBinaryString(leftShift)).replace(' ', '0'));
 
        // 右移
        int rightShift = num1 >> 2;
        System.out.println("8 右移 2 位 = " + rightShift);
        System.out.println("    " + String.format("%32s", Integer.toBinaryString(rightShift)).replace(' ', '0'));
 
        // 负数右移
        int negRightShift = num2 >> 2;
        System.out.println("-8 右移 2 位 = " + negRightShift);
        System.out.println("    " + String.format("%32s", Integer.toBinaryString(negRightShift)).replace(' ', '0'));
 
        // 无符号右移
        int unsignedRightShift = num2 >>> 2;
        System.out.println("-8 无符号右移 2 位 = " + unsignedRightShift);
        System.out.println("    " + String.format("%32s", Integer.toBinaryString(unsignedRightShift)).replace(' ', '0'));
    }
}
 

&位运算

位都为1,结果才为1,否则结果为0。

|位运算

位只要有一个为1,那么结果就是1,否则就为0。

^位运算

两个操作数的位中,相同则结果为0,不同则结果为1。

~位运算

如果位为0,结果是1,如果位为1,结果是0。

三目运算符

  1. 语法格式:条件表达式? 表达式1 : 表达式2
  2. 如果条件表达式为true,则取表达式1的值,否则就取表达式2的值。
public class TernaryDemo {
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
 
        // 使用三目运算符找出最大值
        int max = (a > b) ? a : b;
 
        System.out.println("a = " + a + ", b = " + b);
        System.out.println("max = " + max);
 
        // 嵌套三目运算符找出最小值
        int min = (a < b) ? a : (a == b ? a : b);
        System.out.println("min = " + min);
    }
}
 

运算符优先级

  1. 括号 () 的优先级最高,可以用来强制指定计算顺序。
  2. 一元运算符(如 ++--!)的优先级较高,紧接着是乘法、除法和余数运算符。
  3. 乘法、除法 和 加法、减法 的优先级分别较低。
  4. 比较运算符、逻辑运算符 和 赋值运算符 的优先级逐步降低。
  5. 赋值运算符 = 和三目运算符 ?: 是从右到左计算的。
优先级运算符说明结合性
1()、[]、.方法调用、数组访问、成员访问左到右
2++、—后缀自增、自减左到右
3++、—、+(一元)、-(一元)、~、!前缀自增/自减、一元正负、按位取反、逻辑非右到左
4*、/、%乘法、除法、取余左到右
5+、-加法、减法(字符串拼接也使用 +)左到右
6<<、>>、>>>位移运算(左移、右移、无符号右移)左到右
7<、<=、>、>=、instanceof比较运算、类型检测左到右
8==、!=相等、不相等左到右
9&按位与左到右
10^按位异或左到右
11|按位或左到右
12&&逻辑与(短路与)左到右
13||逻辑或(短路或)左到右
14?:三目条件运算符右到左
15=、+=、-=、*=、/=、%=、&=、^=、|=、<<=、>>=、>>>=赋值与复合赋值右到左
16,逗号运算符(顺序执行多个表达式)左到右

相关文章

评论区