Java 运算符和表达式

31 阅读9分钟

在编程语言中,表达式由操作数(变量、字面量、方法返回值等)和能够作用于这些操作数的运算符组合而成。表达式可以简单到一个单独的值,如 42 或 true,也可以复杂到包含多个运算符和多个操作数的组合,如 (a + b) * (c / d)

运算符定义了对操作数进行的操作,比如算术运算、关系运算或逻辑运算等。在 Java 中,运算符大体上可以分为以下几种类型:

算术运算符

它们用于基本的数学运算。

  • +:加,求两个数的和。
  • -:减,求两个数的差。
  • *:乘,求两个数的积。
  • /:除,求两个数的商。
  • %:余,求两个数相除的余数。

代码示例:

public class ArithmeticOperatorExample {
    public static void main(String[] args) {
        int a = 10, b = 3;
        
        int sum = a + b; // 加法。结果是13
        int diff = a - b; // 减法。结果是7
        int product = a * b; // 乘法。结果是30
        int quotient = a / b; // 除法。结果是3,因为这里使用的是整数除法
        int remainder = a % b; // 取余(模)。结果是1,因为10除以3余数是1
        
        System.out.println(a + " + " + b + " = " + sum); 
        System.out.println(a + " - " + b + " = " + diff);
        System.out.println(a + " * " + b + " = " + product);
        System.out.println(a + " / " + b + " = " + quotient);
        System.out.println(a + " % " + b + " = " + remainder);
    }
}

代码运行结果:

10 + 3 = 13 
10 - 3 = 7 
10 * 3 = 30 
10 / 3 = 3 
10 % 3 = 1

+ 运算符除了用于数值的加法之外,它还可以用来将两个字符串连接在一起,这一过程通常称为字符串的拼接。在进行字符串拼接时,如果任一操作数是字符串类型,Java 会将另一个操作数转换成字符串,并把二者拼接起来。

代码示例:

public class StringConcatenationExample {
    public static void main(String[] args) {
        // 1. 定义两个字符串变量
        String firstName = "张";
        String lastName = "三";

        // 使用 + 运算符来拼接这两个字符串
        String fullName = firstName + lastName;

        // 输出结果
        System.out.println("结果:" + fullName); // 输出 "结果:张三"
        
        // 2. 定义一个字符串和几个其他类型的变量
        String baseString = "结果:";
        int number = 100; 
        double decimal = 3.14; 
        boolean flag = true; 
        
        // 连接字符串和其他类型的数据 
        String combinedString = baseString + number + " | " + decimal + " | " + flag; 
        // 输出结果 
        System.out.println(combinedString); // 输出 "结果:100 | 3.14 | true"
    }
}

代码运行结果:

结果:张三
结果:100 | 3.14 | true

一元运算符

一元操作符(Unary Operator)只需要一个操作数来进行操作或计算。例如对变量进行自增或自减,或者改变布尔值的逻辑状态。

常见的一元操作符包括:

  • +:正数,不写默认也是正数。
  • -:负数。
  • ++:自增,将变量增加1。
  • --:自减,将变量减去1。
  • !:逻辑非,用于取布尔值的相反值。如果原来是 true,则变为 false,反之亦然。

代码示例:

public class UnaryOperatorExample {
    public static void main(String[] args) {
        int a = +3, b = -5;
        
        int postIncrement = a++; // 自增。先使用a的值,然后a增加1,a变为4,postIncrement是3
        int preIncrement = ++b; // 自增。b先增加1变为-4,然后赋值,preIncrement是-4 
        System.out.println("a++ = " + postIncrement);
        System.out.println("++b = " + preIncrement); 
        
        int postDecrement = a--; // 自减。先使用a的值,然后a减去1,a回到3,postDecrement是4
        int preDecrement = --b; // 自减。b先减去1变为-5,然后赋值,preDecrement是-5
        System.out.println("a-- = " + postDecrement); 
        System.out.println("--b = " + preDecrement);
        
        boolean success = true;
        boolean not = !success; // 逻辑非。true 取反变成 false
        System.out.println("!" + success + " = " + not); // 输出 "!success = false"
    }
}

代码运行结果:

a++ = 3
++b = -4
a-- = 4
--b = -5
!true = false

关系运算符

用于比较两个操作数之间的关系。

  • ==:等于,如果两个操作数的值相等,结果是true
  • !=:不等于,如果两个操作数的值不相等,结果是true
  • >:大于,如果左操作数的值大于右操作数,结果是true
  • <:小于,如果左操作数的值小于右操作数,结果是true
  • >=:大于等于,如果左操作数的值大于或等于右操作数,结果是true
  • <=:小于等于,如果左操作数的值小于或等于右操作数,结果是true

代码示例:

public class RelationalOperatorExample { 
    public static void main(String[] args) {
        int c = 20, d = 10;

        boolean isEqual = c == d; // 相等。结果是false,因为20不等于10
        boolean isNotEqual = c != d; // 不等。结果是true,因为20不等于10
        boolean isGreater = c > d; // 大于。结果是true,因为20大于10
        boolean isLess = c < d; // 小于。结果是false,因为20不小于10
        boolean isGreaterOrEqual = c >= d; // 大于等于。结果是true,因为20大于等于10
        boolean isLessOrEqual = c <= d; // 小于等于。结果是false,因为20不小于等于10

        System.out.println(c + " == " + d + ": " + isEqual); 
        System.out.println(c + " != " + d + ": " + isNotEqual); 
        System.out.println(c + " > " + d + ": " + isGreater); 
        System.out.println(c + " < " + d + ": " + isLess); 
        System.out.println(c + " >= " + d + ": " + isGreaterOrEqual); 
        System.out.println(c + " <= " + d + ": " + isLessOrEqual); 
        System.out.println(c + " != " + d + ": " + isLessOrEqual); 
    }
}

代码运算结果:

20 == 10: false
20 != 10: true
20 > 10: true
20 < 10: false
20 >= 10: true
20 <= 10: false
20 != 10: false

逻辑运算符

用于基于一个或两个操作数的布尔值推导出结果。

  • &&:逻辑与,当所有操作数都为true时,结果是true
  • ||:逻辑或,当至少一个操作数为true时,结果是true

代码示例:

public class LogicOperators { 
    public static void main(String[] args) {
        boolean x = true, y = false;

        boolean and = (x && y); // 逻辑与。结果是false,因为并非两个操作数都是true
        boolean or = (x || y); // 逻辑或。结果是true,因为至少有一个操作数是true
        
        System.out.println(x + " && " + y + " = " + and); 
        System.out.println(x + " || " + y + " = " + or); 
    }
}

代码运行结果:

true && false = false
true || false = true

条件运算符(也称为三元运算符)

格式为条件表达式 ? 表达式1 : 表达式2。如果条件表达式的值为true,则结果是表达式1的值;否则结果是表达式2的值。

代码示例:

public class TernaryOperatorExample { 
    public static void main(String[] args) {
        int h = 2, i = 5;

        int max = (h > i) ? h : i; // 判断h是否大于i,如果是,则max等于h,否则等于i。结果是5。
        
        System.out.println(2 + " > " + i + " ? " + h + " : " + i + " = " + max); // 结果是5
    }
}

代码运行结果:

2 > 5 ? 2 : 5 = 5

位运算符(不常用)

这些运算符用于直接操作整数类型操作数的二进制位,但很少被使用。

  • 位与 &:对两个操作数按位进行与操作。
  • 位或 |:对两个操作数按位进行或操作。
  • 位异或 ^:对两个操作数按位进行异或操作(当两个相应的二进位相异时,结果为1)。
  • 按位取反 ~:翻转操作数的每一位。
  • 左移 <<:将操作数的二进制表示向左移动指定位数,右侧空出的位用0填充。
  • 右移 >>:将操作数的二进制表示向右移动指定位数,左侧空出的位用符号位填充。
  • 无符号右移 >>>:将操作数的二进制表示向右移动指定位数,左侧空出的位用0填充。

代码示例:

public class BitwiseOperatorExample { 
    public static void main(String[] args) {
        int e = 12; // 二进制表示为1100
        int f = 6;  // 二进制表示为0110

        int andBitwise = e & f; // 按位与。结果是4,二进制为0100
        int orBitwise = e | f; // 按位或。结果是14,二进制为1110
        int xorBitwise = e ^ f; // 按位异或。结果是10,二进制为1010
        int notBitwise = ~e; // 按位取反。结果是-13
        int leftShift = e << 1; // 左移。结果是24,二进制为11000
        int rightShift = e >> 1; // 右移。结果是6,二进制为0110
        int unsignedRightShift = -12 >>> 1; // 无符号右移。正数结果与常规右移相同,负数在左边填充零
        
        System.out.println(e + " & " + " f " + " = " + andBitwise);
        System.out.println(e + " | " + " f " + " = " + orBitwise);
        System.out.println(e + " ^ " + " f " + " = " + xorBitwise);
        System.out.println("~" + e + " = " + notBitwise);
        System.out.println(e + " << 1 = " + leftShift);
        System.out.println(e + " >> 1 = " + rightShift);
        System.out.println("-12 >>> 1 = " + unsignedRightShift);
    }
}

代码运算结果:

12 &  f  = 4
12 |  f  = 14
12 ^  f  = 10
~12 = -13
12 << 1 = 24
12 >> 1 = 6
-12 >>> 1 = 2147483642

赋值运算符

用来将表达式的值分配给变量。

  • 简单赋值 =:将右边表达式的值分配给左边的操作数。
  • 复合赋值 +=-=*=/=%=&=|=^=<<=>>=>>>=:它是将赋值与另一个操作(如加法)结合在一起的快捷方式,例如 a += b 相当于 a = a + b

代码示例:

public class AssignmentOperatorExample {
    public static void main(String[] args) {
        int g = 5;

        System.out.println("g = " + g);
        g += 3; // 等同于 g = g + 3; g的结果是8
        System.out.println(g + " += 3 = " + g);

        g -= 2; // 等同于 g = g - 2; g的结果是6
        System.out.println(g + " -= 2 = " + g);

        g *= 2; // 等同于 g = g * 2; g的结果是12
        System.out.println(g + " *= 2 = " + g);

        g /= 3; // 等同于 g = g / 3; g的结果是4
        System.out.println(g + " /= 3 = " + g);

        g %= 3; // 等同于 g = g % 3; g的结果是1
        System.out.println(g + " %= 3 = " + g);

        g &= 3; // 等同于 g = g & 3; g的结果是1 
        System.out.println(g + " &= 3 = " + g);

        g |= 2; // 等同于 g = g | 2; g的结果是3 
        System.out.println(g + " |= 2 = " + g);

        g ^= 3; // 等同于 g = g ^ 3; g的结果是0 
        System.out.println(g + " ^= 3 = " + g);

        g <<= 1; // 等同于 g = g << 1; g的结果是0 
        System.out.println(g + " <<= 1 = " + g);

        g >>= 1; // 等同于 g = g >> 1; g的结果是0 
        System.out.println(g + " >>= 1 = " + g);

        g >>>= 1; // 等同于 g = g >>> 1; g的结果是0 
        System.out.println(g + " >>>= 1 = " + g);
    }
}

代码运行结果:

g = 5
8 += 3 = 8
6 -= 2 = 6
12 *= 2 = 12
4 /= 3 = 4
1 %= 3 = 1
1 &= 3 = 1

类型比较运算符

instanceof是用于确定一个对象是否是特定类的一个实例,这涉及到面向对象的知识。

代码示例:

public class InstanceOfOperatorExample { 
    public static void main(String[] args) { 
        Object obj = "Hello"; 
        // 使用 instanceof 运算符检查对象是否是特定类的一个实例 
        boolean isStringInstance = obj instanceof String; 
        
        System.out.println(obj + " 是 String 的实例: " + isStringInstance); 
    } 
}

代码运行结果:

Hello 是 String 的实例: true

类型转换运算符

用于将变量从一种类型转换成另一种类型,例如 (int) 23.7 将23.7的类型从double强制转换为int,丢弃小数部分。

代码示例:

public class TypeConversionExample {
    public static void main(String[] args) {
        double j = 9.5;
        // 强制类型转换
        int k = (int) j; // j的值被强制转换成整数类型,小数点后的部分被切掉。k的结果是9。
        System.out.println(k); // 输出结果为 9
    }
}

代码运行结果:

9

在组合操作数和运算符来编写表达式的时候,你必须考虑操作符的优先级和结合性。优先级决定了哪些运算符先进行计算,结合性决定了当有两个相同优先级的运算符时计算的方向(从左到右或从右到左)。使用圆括号()可以改变计算的顺序,因为它具有最高的优先级。