BenChuat

Background
跳过正文

Java运算符与表达式总结整理串讲

·11673 字·24 分钟
作者
BenChuat
A little bit about BenChuat.
目录

Java运算符与表达式总结整理串讲
#

一、运算符概述
#

1.1 什么是运算符
#

运算符(Operator)是用来对操作数进行运算的符号。Java提供了丰富的运算符,用于执行各种计算和逻辑操作。

1.2 运算符的分类
#

Java运算符可以分为以下几类:

  1. 算术运算符
  2. 关系运算符(比较运算符)
  3. 逻辑运算符
  4. 位运算符
  5. 赋值运算符
  6. 条件运算符(三元运算符)
  7. 其他运算符(instanceof、new等)

二、算术运算符
#

2.1 基本算术运算符
#

运算符名称功能示例
+加法两数相加3 + 5 = 8
-减法两数相减10 - 3 = 7
*乘法两数相乘4 * 5 = 20
/除法两数相除10 / 3 = 3(整数)
%取模(取余)求余数10 % 3 = 1

示例代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
public class ArithmeticOperators {
    public static void main(String[] args) {
        int a = 10;
        int b = 3;
        
        System.out.println("a = " + a + ", b = " + b);
        System.out.println("a + b = " + (a + b));  // 13
        System.out.println("a - b = " + (a - b));  // 7
        System.out.println("a * b = " + (a * b));  // 30
        System.out.println("a / b = " + (a / b));  // 3(整数除法)
        System.out.println("a % b = " + (a % b));  // 1
        
        // 浮点数除法
        double x = 10.0;
        double y = 3.0;
        System.out.println("x / y = " + (x / y));  // 3.3333333333333335
    }
}

2.2 自增自减运算符
#

运算符名称功能示例
++自增操作数加1a++++a
自减操作数减1a----a

前置和后置的区别:

  • 前置(++a):先自增,再使用
  • 后置(a++):先使用,再自增

示例代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class IncrementDecrement {
    public static void main(String[] args) {
        int a = 5;
        
        // 后置自增
        System.out.println("a = " + a);        // 5
        System.out.println("a++ = " + a++);    // 5(先使用,再自增)
        System.out.println("a = " + a);        // 6
        
        int b = 5;
        // 前置自增
        System.out.println("b = " + b);        // 5
        System.out.println("++b = " + ++b);   // 6(先自增,再使用)
        System.out.println("b = " + b);        // 6
        
        // 自减示例
        int c = 5;
        System.out.println("c-- = " + c--);    // 5
        System.out.println("c = " + c);       // 4
        
        int d = 5;
        System.out.println("--d = " + --d);   // 4
        System.out.println("d = " + d);       // 4
    }
}

2.3 字符串连接运算符
#

+ 运算符在操作字符串时,用于连接字符串。

示例代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
public class StringConcatenation {
    public static void main(String[] args) {
        String str1 = "Hello";
        String str2 = "World";
        String result = str1 + " " + str2;
        System.out.println(result);  // Hello World
        
        // 字符串与数字连接
        int num = 100;
        String str3 = "数字是: " + num;
        System.out.println(str3);  // 数字是: 100
        
        // 注意运算顺序
        System.out.println("结果: " + 10 + 20);  // 结果: 1020(字符串连接)
        System.out.println("结果: " + (10 + 20));  // 结果: 30(先计算,再连接)
    }
}

三、关系运算符(比较运算符)
#

关系运算符用于比较两个值,返回布尔类型(true或false)。

运算符名称功能示例结果
==等于判断两值是否相等5 == 5true
!=不等于判断两值是否不相等5 != 3true
>大于判断左值是否大于右值5 > 3true
<小于判断左值是否小于右值5 < 3false
>=大于等于判断左值是否大于等于右值5 >= 5true
<=小于等于判断左值是否小于等于右值5 <= 3false

示例代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class RelationalOperators {
    public static void main(String[] args) {
        int a = 10;
        int b = 5;
        
        System.out.println("a = " + a + ", b = " + b);
        System.out.println("a == b: " + (a == b));  // false
        System.out.println("a != b: " + (a != b));  // true
        System.out.println("a > b: " + (a > b));    // true
        System.out.println("a < b: " + (a < b));    // false
        System.out.println("a >= b: " + (a >= b));  // true
        System.out.println("a <= b: " + (a <= b));  // false
        
        // 注意:== 比较的是值(基本类型)或引用(引用类型)
        String str1 = "Hello";
        String str2 = "Hello";
        String str3 = new String("Hello");
        System.out.println("str1 == str2: " + (str1 == str2));  // true(字符串常量池)
        System.out.println("str1 == str3: " + (str1 == str3));  // false(不同对象)
        System.out.println("str1.equals(str3): " + str1.equals(str3));  // true(内容相同)
    }
}

四、逻辑运算符
#

逻辑运算符用于连接布尔表达式,返回布尔值。

4.1 基本逻辑运算符
#

运算符名称功能示例结果
&&逻辑与(短路)两个条件都为true才返回truetrue && falsefalse
||逻辑或(短路)至少一个条件为true就返回truetrue || falsetrue
!逻辑非取反!truefalse
&逻辑与(非短路)两个条件都为true才返回truetrue & falsefalse
|逻辑或(非短路)至少一个条件为true就返回truetrue | falsetrue
^逻辑异或两个条件不同时返回truetrue ^ falsetrue

4.2 短路与非短路的区别
#

  • 短路运算符(&&、||):如果第一个操作数已经能确定结果,就不再计算第二个操作数
  • 非短路运算符(&、|):无论第一个操作数结果如何,都会计算第二个操作数

示例代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class LogicalOperators {
    public static void main(String[] args) {
        boolean a = true;
        boolean b = false;
        
        // 基本逻辑运算
        System.out.println("a && b: " + (a && b));  // false
        System.out.println("a || b: " + (a || b));  // true
        System.out.println("!a: " + (!a));          // false
        System.out.println("a ^ b: " + (a ^ b));     // true
        
        // 短路与非短路的区别
        int x = 5;
        int y = 10;
        
        // 短路与:如果第一个为false,不执行第二个
        if (x > 10 && y++ > 5) {
            // 不会执行
        }
        System.out.println("y = " + y);  // 10(y++未执行)
        
        int z = 10;
        // 非短路与:即使第一个为false,也执行第二个
        if (x > 10 & z++ > 5) {
            // 不会执行
        }
        System.out.println("z = " + z);  // 11(z++已执行)
        
        // 短路或:如果第一个为true,不执行第二个
        int m = 5;
        int n = 10;
        if (m < 10 || n++ > 5) {
            // 会执行
        }
        System.out.println("n = " + n);  // 10(n++未执行)
    }
}

4.3 逻辑运算符真值表
#

ABA && BA || B!AA ^ B
truetruetruetruefalsefalse
truefalsefalsetruefalsetrue
falsetruefalsetruetruetrue
falsefalsefalsefalsetruefalse

五、位运算符
#

位运算符对整数的二进制位进行操作。

运算符名称功能示例
&按位与两个位都为1时结果为15 & 3 = 1
|按位或至少一个位为1时结果为15 | 3 = 7
^按位异或两个位不同时结果为15 ^ 3 = 6
~按位取反0变1,1变0~5 = -6
«左移左移指定位数,右边补05 << 1 = 10
»右移右移指定位数,左边补符号位-5 >> 1 = -3
»>无符号右移右移指定位数,左边补0-5 >>> 1 = 2147483645

示例代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class BitwiseOperators {
    public static void main(String[] args) {
        int a = 5;  // 二进制:0101  
        int b = 3;  // 二进制:0011
        
        System.out.println("a = " + a + " (二进制: " + Integer.toBinaryString(a) + ")");
        System.out.println("b = " + b + " (二进制: " + Integer.toBinaryString(b) + ")");
        
        // 按位与
        System.out.println("a & b = " + (a & b));  // 1 (0001)
        
        // 按位或
        System.out.println("a | b = " + (a | b));  // 7 (0111)
        
        // 按位异或
        System.out.println("a ^ b = " + (a ^ b));  // 6 (0110)
        
        // 按位取反
        System.out.println("~a = " + (~a));  // -6
        
        // 左移
        System.out.println("a << 1 = " + (a << 1));  // 10 (1010)
        
        // 右移
        System.out.println("a >> 1 = " + (a >> 1));  // 2 (0010)
        
        // 无符号右移
        int c = -5;
        System.out.println("c >>> 1 = " + (c >>> 1));
    }
}

5.1 位运算应用示例
#

示例1:判断奇偶数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public class BitwiseApplications {
    public static void main(String[] args) {
        int num = 10;
        // 使用位运算判断奇偶:偶数的最低位为0
        if ((num & 1) == 0) {
            System.out.println(num + " 是偶数");
        } else {
            System.out.println(num + " 是奇数");
        }
    }
}

示例2:交换两个数(不使用临时变量)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public class SwapWithoutTemp {
    public static void main(String[] args) {
        int a = 5;
        int b = 10;
        
        System.out.println("交换前: a = " + a + ", b = " + b);
        
        // 使用异或运算交换
        a = a ^ b;
        b = a ^ b;
        a = a ^ b;
        
        System.out.println("交换后: a = " + a + ", b = " + b);
    }
}

六、赋值运算符
#

6.1 基本赋值运算符
#

= 是最基本的赋值运算符。

6.2 复合赋值运算符
#

复合赋值运算符结合了算术运算和赋值运算。

运算符等价于示例
+=a = a + ba += 5 等价于 a = a + 5
-=a = a - ba -= 5 等价于 a = a - 5
*=a = a * ba *= 5 等价于 a = a * 5
/=a = a / ba /= 5 等价于 a = a / 5
%=a = a % ba %= 5 等价于 a = a % 5
&=a = a & ba &= 5 等价于 a = a & 5
|=a = a | ba |= 5 等价于 a = a | 5
^=a = a ^ ba ^= 5 等价于 a = a ^ 5
«=a = a « ba <<= 1 等价于 a = a << 1
»=a = a » ba >>= 1 等价于 a = a >> 1
»>=a = a »> ba >>>= 1 等价于 a = a >>> 1

示例代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
public class AssignmentOperators {
    public static void main(String[] args) {
        int a = 10;
        
        a += 5;  // a = a + 5 = 15
        System.out.println("a += 5: " + a);
        
        a -= 3;  // a = a - 3 = 12
        System.out.println("a -= 3: " + a);
        
        a *= 2;  // a = a * 2 = 24
        System.out.println("a *= 2: " + a);
        
        a /= 4;  // a = a / 4 = 6
        System.out.println("a /= 4: " + a);
        
        a %= 4;  // a = a % 4 = 2
        System.out.println("a %= 4: " + a);
    }
}

七、条件运算符(三元运算符)
#

条件运算符是Java中唯一的三元运算符,格式为:条件 ? 表达式1 : 表达式2

语法:

1
result = condition ? valueIfTrue : valueIfFalse;

示例代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
public class TernaryOperator {
    public static void main(String[] args) {
        int a = 10;
        int b = 5;
        
        // 找出最大值
        int max = (a > b) ? a : b;
        System.out.println("最大值: " + max);
        
        // 判断奇偶数
        String result = (a % 2 == 0) ? "偶数" : "奇数";
        System.out.println(a + " 是 " + result);
        
        // 嵌套使用
        int c = 15;
        int maxOfThree = (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);
        System.out.println("三个数中的最大值: " + maxOfThree);
    }
}

八、运算符优先级
#

运算符优先级决定了表达式中运算的执行顺序。优先级高的运算符先执行。

8.1 运算符优先级表(从高到低)
#

优先级运算符结合性说明
1() [] .左→右括号、数组下标、成员访问
2++ – ! ~右→左自增自减、逻辑非、按位取反
3* / %左→右乘除取模
4+ -左→右加减
5« » »>左→右位移运算
6< > <= >= instanceof左→右关系运算
7== !=左→右相等性判断
8&左→右按位与
9^左→右按位异或
10|左→右按位或
11&&左→右逻辑与
12||左→右逻辑或
13? :右→左三元运算符
14= += -= *= /= %= 等右→左赋值运算符

示例代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
public class OperatorPrecedence {
    public static void main(String[] args) {
        int a = 5;
        int b = 3;
        int c = 2;
        
        // 注意运算符优先级
        int result1 = a + b * c;  // 先算乘法,再算加法:5 + 6 = 11
        System.out.println("a + b * c = " + result1);
        
        int result2 = (a + b) * c;  // 先算括号,再算乘法:8 * 2 = 16
        System.out.println("(a + b) * c = " + result2);
        
        boolean result3 = a > b && b > c;  // 先算关系运算,再算逻辑与
        System.out.println("a > b && b > c = " + result3);
        
        int result4 = a++ + ++b;  // 先算++b,再算a++,最后相加
        System.out.println("a++ + ++b = " + result4);
        System.out.println("a = " + a + ", b = " + b);
    }
}

九、表达式
#

9.1 什么是表达式
#

表达式(Expression)是由运算符、操作数和括号组成的,可以计算出一个值的式子。

表达式的特点:

  • 表达式有值
  • 表达式可以嵌套
  • 表达式的结果类型由运算符和操作数决定

9.2 表达式类型
#

表达式类型说明示例
算术表达式使用算术运算符a + b * c
关系表达式使用关系运算符,返回booleana > b
逻辑表达式使用逻辑运算符,返回booleana > b && c < d
赋值表达式使用赋值运算符a = b + c
条件表达式使用三元运算符a > b ? a : b

示例代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class Expressions {
    public static void main(String[] args) {
        int a = 10;
        int b = 5;
        int c = 3;
        
        // 算术表达式
        int result1 = a + b * c;
        System.out.println("算术表达式: " + result1);
        
        // 关系表达式
        boolean result2 = a > b && b > c;
        System.out.println("关系表达式: " + result2);
        
        // 逻辑表达式
        boolean result3 = (a > b) || (c > a);
        System.out.println("逻辑表达式: " + result3);
        
        // 赋值表达式
        int result4 = a += b;  // a = a + b,然后返回a的值
        System.out.println("赋值表达式: " + result4);
        
        // 条件表达式
        int result5 = a > b ? a : b;
        System.out.println("条件表达式: " + result5);
        
        // 复合表达式
        int result6 = (a + b) * (c - 1) + (a % b);
        System.out.println("复合表达式: " + result6);
    }
}

十、练习题
#

练习题1:算术运算符
#

请分析以下代码的输出结果:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public class Exercise1 {
    public static void main(String[] args) {
        int a = 10;
        int b = 3;
        
        System.out.println(a / b);
        System.out.println(a % b);
        System.out.println(a++);
        System.out.println(++a);
        System.out.println(b--);
        System.out.println(--b);
    }
}

参考答案:

1
2
3
4
5
6
3
1
10
12
3
1

练习题2:关系运算符
#

请编写代码,判断一个年份是否为闰年。 闰年条件:能被4整除但不能被100整除,或者能被400整除。

参考答案:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public class Exercise2 {
    public static void main(String[] args) {
        int year = 2024;
        
        boolean isLeapYear = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
        
        if (isLeapYear) {
            System.out.println(year + " 是闰年");
        } else {
            System.out.println(year + " 不是闰年");
        }
    }
}

练习题3:逻辑运算符
#

请分析以下代码的输出结果:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
public class Exercise3 {
    public static void main(String[] args) {
        int x = 5;
        int y = 10;
        int z = 15;
        
        boolean result1 = x > 3 && y < 20;
        boolean result2 = x > 10 || y < 5;
        boolean result3 = !(x > 10);
        boolean result4 = x > 3 && y < 5 || z > 10;
        
        System.out.println("result1: " + result1);
        System.out.println("result2: " + result2);
        System.out.println("result3: " + result3);
        System.out.println("result4: " + result4);
    }
}

参考答案:

1
2
3
4
result1: true
result2: false
result3: true
result4: true

练习题4:位运算符
#

请编写代码实现以下功能:

  1. 使用位运算判断一个数是否为2的幂
  2. 使用位运算计算两个数的最大公约数(简化版)

参考答案:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
public class Exercise4 {
    public static void main(String[] args) {
        // 1. 判断是否为2的幂
        int num = 16;
        // 2的幂的二进制表示只有一个1,如:16 = 10000
        // num & (num - 1) 如果为0,说明是2的幂
        boolean isPowerOfTwo = (num > 0) && ((num & (num - 1)) == 0);
        System.out.println(num + " 是2的幂? " + isPowerOfTwo);
        
        // 2. 使用位运算交换两个数
        int a = 5;
        int b = 10;
        System.out.println("交换前: a = " + a + ", b = " + b);
        
        a = a ^ b;
        b = a ^ b;
        a = a ^ b;
        
        System.out.println("交换后: a = " + a + ", b = " + b);
    }
}

练习题5:运算符优先级
#

请分析以下表达式的值,并说明计算过程:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
public class Exercise5 {
    public static void main(String[] args) {
        int a = 5;
        int b = 3;
        int c = 2;
        
        int result1 = a + b * c;
        int result2 = (a + b) * c;
        int result3 = a++ + ++b * c;
        boolean result4 = a > b && b > c || a < c;
        
        System.out.println("result1: " + result1);
        System.out.println("result2: " + result2);
        System.out.println("result3: " + result3);
        System.out.println("result4: " + result4);
    }
}

参考答案:

1
2
3
4
result1: 11  (5 + 3 * 2 = 5 + 6 = 11)
result2: 16  ((5 + 3) * 2 = 8 * 2 = 16)
result3: 14  (5 + 4 * 2 = 5 + 8 = 13, 但a++后a=6, b=4)
result4: true  ((6 > 4 && 4 > 2) || (6 < 2) = (true && true) || false = true)

练习题6:综合应用
#

请编写一个程序,实现以下功能:

  1. 输入三个数,使用三元运算符找出最大值
  2. 判断这三个数能否构成三角形(任意两边之和大于第三边)
  3. 如果构成三角形,判断是等边、等腰还是普通三角形

参考答案:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class Exercise6 {
    public static void main(String[] args) {
        int a = 5;
        int b = 5;
        int c = 5;
        
        // 1. 找出最大值
        int max = (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);
        System.out.println("最大值: " + max);
        
        // 2. 判断能否构成三角形
        boolean canFormTriangle = (a + b > c) && (a + c > b) && (b + c > a);
        
        if (canFormTriangle) {
            System.out.println("可以构成三角形");
            
            // 3. 判断三角形类型
            if (a == b && b == c) {
                System.out.println("等边三角形");
            } else if (a == b || a == c || b == c) {
                System.out.println("等腰三角形");
            } else {
                System.out.println("普通三角形");
            }
        } else {
            System.out.println("不能构成三角形");
        }
    }
}

十一、运算符与表达式对比分析表
#

11.1 算术运算符对比
#

运算符功能操作数类型结果类型注意事项
+加法/字符串连接数值/字符串数值/字符串字符串+数字会转换为字符串
-减法数值数值只能用于数值类型
*乘法数值数值注意溢出问题
/除法数值数值整数除法会截断小数部分
%取模数值数值结果的符号与被除数相同
++自增数值数值前置和后置的区别
自减数值数值前置和后置的区别

11.2 关系运算符对比
#

运算符功能操作数类型结果类型注意事项
==等于任意boolean基本类型比较值,引用类型比较引用
!=不等于任意boolean基本类型比较值,引用类型比较引用
>大于数值boolean只能用于数值类型
<小于数值boolean只能用于数值类型
>=大于等于数值boolean只能用于数值类型
<=小于等于数值boolean只能用于数值类型

11.3 逻辑运算符对比
#

运算符名称短路特性使用场景性能
&&逻辑与(短路)常用,推荐更好(可能提前结束)
||逻辑或(短路)常用,推荐更好(可能提前结束)
!逻辑非取反操作无影响
&逻辑与(非短路)需要计算所有条件较差
|逻辑或(非短路)需要计算所有条件较差
^逻辑异或判断两个条件不同无影响

11.4 位运算符对比
#

运算符功能操作数类型结果类型应用场景
&按位与整数整数掩码操作、判断奇偶
|按位或整数整数设置特定位
^按位异或整数整数交换变量、加密
~按位取反整数整数取反操作
«左移整数整数快速乘以2的幂
»右移整数整数快速除以2的幂(有符号)
»>无符号右移整数整数快速除以2的幂(无符号)

11.5 赋值运算符对比
#

运算符等价表达式使用场景性能
=a = b基本赋值标准
+=a = a + b累加操作相同
-=a = a - b递减操作相同
*=a = a * b累乘操作相同
/=a = a / b除法赋值相同
%=a = a % b取模赋值相同
&=a = a & b位与赋值相同
|=a = a | b位或赋值相同
^=a = a ^ b位异或赋值相同
«=a = a « b左移赋值相同
»=a = a » b右移赋值相同
»>=a = a »> b无符号右移赋值相同

11.6 运算符优先级总结
#

优先级运算符类别运算符结合性
最高括号、访问() [] .左→右
单目运算符++ – ! ~右→左
中高乘除取模* / %左→右
加减+ -左→右
中低位移« » »>左→右
关系< > <= >=左→右
相等== !=左→右
位运算& ^ |左→右
逻辑&& ||左→右
最低条件、赋值? : = += 等右→左

11.7 表达式类型对比
#

表达式类型运算符结果类型典型应用
算术表达式+ - * / %数值数学计算
关系表达式== != > < >= <=boolean条件判断
逻辑表达式&& || !boolean复合条件
位运算表达式& | ^ ~ « »整数位操作、优化
赋值表达式= += -= 等赋值类型变量赋值
条件表达式? :表达式类型条件选择

十二、拓展:正则表达式
#

12.1 什么是正则表达式
#

正则表达式(Regular Expression,简称Regex)是一种用来描述字符串模式的工具,可以用来匹配、查找、替换字符串。

12.2 Java中的正则表达式
#

Java中使用java.util.regex包来处理正则表达式,主要包含两个类:

  • Pattern:编译正则表达式
  • Matcher:执行匹配操作

12.3 基本语法
#

字符类
#

表达式说明示例
.匹配除换行符外的任意字符a.c 匹配 “abc”、“a1c”
[abc]匹配a、b或c中的任意一个[abc] 匹配 “a”、“b”、“c”
[^abc]匹配除a、b、c外的任意字符[^abc] 匹配 “d”、“1”
[a-z]匹配a到z的任意小写字母[a-z] 匹配 “a”、“b”、“z”
[A-Z]匹配A到Z的任意大写字母[A-Z] 匹配 “A”、“B”、“Z”
[0-9]匹配0到9的任意数字[0-9] 匹配 “0”、“5”、“9”
\d匹配数字,等价于[0-9]\d 匹配 “0”、“9”
\D匹配非数字,等价于[^0-9]\D 匹配 “a”、"@"
\w匹配单词字符(字母、数字、下划线)\w 匹配 “a”、“1”、"_"
\W匹配非单词字符\W 匹配 “@"、” "
\s匹配空白字符(空格、制表符等)\s 匹配 " “、"\t”
\S匹配非空白字符\S 匹配 “a”、“1”

示例代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class RegexBasic {
    public static void main(String[] args) {
        String text = "Hello World 123";
        
        // 匹配数字
        Pattern pattern1 = Pattern.compile("\\d");
        Matcher matcher1 = pattern1.matcher(text);
        System.out.println("数字:");
        while (matcher1.find()) {
            System.out.print(matcher1.group() + " ");
        }
        System.out.println();
        
        // 匹配字母
        Pattern pattern2 = Pattern.compile("[a-zA-Z]");
        Matcher matcher2 = pattern2.matcher(text);
        System.out.println("字母:");
        while (matcher2.find()) {
            System.out.print(matcher2.group() + " ");
        }
        System.out.println();
    }
}

量词
#

表达式说明示例
*匹配0次或多次a* 匹配 “"、“a”、“aa”
+匹配1次或多次a+ 匹配 “a”、“aa”
?匹配0次或1次a? 匹配 “"、“a”
{n}匹配恰好n次a{3} 匹配 “aaa”
{n,}匹配至少n次a{2,} 匹配 “aa”、“aaa”
{n,m}匹配n到m次a{2,4} 匹配 “aa”、“aaa”、“aaaa”

示例代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class RegexQuantifiers {
    public static void main(String[] args) {
        String[] texts = {"a", "aa", "aaa", "aaaa", "b"};
        Pattern pattern = Pattern.compile("a{2,3}");  // 匹配2到3个a
        
        for (String text : texts) {
            Matcher matcher = pattern.matcher(text);
            System.out.println(text + " 匹配: " + matcher.matches());
        }
    }
}

边界匹配
#

表达式说明示例
^匹配字符串开始^Hello 匹配以"Hello"开头的字符串
$匹配字符串结束World$ 匹配以"World"结尾的字符串
\b匹配单词边界\bword\b 匹配独立的"word”
\B匹配非单词边界\Bword\B 匹配非独立的"word”

示例代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class RegexBoundaries {
    public static void main(String[] args) {
        String text = "Hello World Hello";
        
        // 匹配以Hello开头的字符串
        Pattern pattern1 = Pattern.compile("^Hello");
        Matcher matcher1 = pattern1.matcher(text);
        System.out.println("以Hello开头: " + matcher1.find());
        
        // 匹配单词边界
        Pattern pattern2 = Pattern.compile("\\bHello\\b");
        Matcher matcher2 = pattern2.matcher(text);
        int count = 0;
        while (matcher2.find()) {
            count++;
        }
        System.out.println("单词Hello出现次数: " + count);
    }
}

分组和引用
#

表达式说明示例
()分组(ab)+ 匹配 “ab”、“abab”
|a|b 匹配 “a"或"b”
\1引用第一个分组(a)\1 匹配 “aa”

示例代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class RegexGroups {
    public static void main(String[] args) {
        String text = "2024-01-15";
        Pattern pattern = Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})");
        Matcher matcher = pattern.matcher(text);
        
        if (matcher.matches()) {
            System.out.println("完整匹配: " + matcher.group(0));
            System.out.println("年份: " + matcher.group(1));
            System.out.println("月份: " + matcher.group(2));
            System.out.println("日期: " + matcher.group(3));
        }
    }
}

12.4 String类中的正则表达式方法
#

matches() - 判断是否匹配
#

1
2
3
String str = "12345";
boolean matches = str.matches("\\d+");  // 判断是否全为数字
System.out.println(matches);  // true

split() - 分割字符串
#

1
2
3
4
5
String str = "apple,banana,orange";
String[] fruits = str.split(",");
for (String fruit : fruits) {
    System.out.println(fruit);
}

replaceAll() - 替换所有匹配
#

1
2
3
String str = "Hello123World456";
String result = str.replaceAll("\\d+", "数字");
System.out.println(result);  // Hello数字World数字

replaceFirst() - 替换第一个匹配
#

1
2
3
String str = "Hello123World456";
String result = str.replaceFirst("\\d+", "数字");
System.out.println(result);  // Hello数字World456

综合示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class StringRegexMethods {
    public static void main(String[] args) {
        // 1. matches() - 验证邮箱格式
        String email = "user@example.com";
        boolean isValidEmail = email.matches("[\\w.-]+@[\\w.-]+\\.[a-zA-Z]{2,}");
        System.out.println("邮箱格式正确? " + isValidEmail);
        
        // 2. split() - 分割字符串
        String text = "apple,banana,orange";
        String[] fruits = text.split(",");
        System.out.println("分割结果:");
        for (String fruit : fruits) {
            System.out.println(fruit);
        }
        
        // 3. replaceAll() - 替换所有数字
        String str1 = "价格是100元,折扣是20%";
        String result1 = str1.replaceAll("\\d+", "X");
        System.out.println("替换后: " + result1);
        
        // 4. replaceFirst() - 替换第一个数字
        String str2 = "价格是100元,折扣是20%";
        String result2 = str2.replaceFirst("\\d+", "X");
        System.out.println("替换后: " + result2);
    }
}

12.5 常用正则表达式示例
#

验证手机号
#

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public class PhoneValidation {
    public static void main(String[] args) {
        String[] phones = {"13812345678", "15912345678", "12345678901", "1381234"};
        String regex = "1[3-9]\\d{9}";  // 1开头,第二位3-9,后面9位数字
        
        for (String phone : phones) {
            boolean isValid = phone.matches(regex);
            System.out.println(phone + " 是否有效: " + isValid);
        }
    }
}

验证邮箱
#

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
public class EmailValidation {
    public static void main(String[] args) {
        String[] emails = {
            "user@example.com",
            "test.email@domain.co.uk",
            "invalid.email",
            "@domain.com"
        };
        String regex = "[\\w.-]+@[\\w.-]+\\.[a-zA-Z]{2,}";
        
        for (String email : emails) {
            boolean isValid = email.matches(regex);
            System.out.println(email + " 是否有效: " + isValid);
        }
    }
}

验证身份证号
#

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
public class IDCardValidation {
    public static void main(String[] args) {
        String[] idCards = {
            "110101199001011234",
            "11010119900101123X",
            "12345678901234567",
            "11010119900101123"
        };
        String regex = "\\d{17}[\\dXx]";  // 18位,最后一位可以是数字或X
        
        for (String idCard : idCards) {
            boolean isValid = idCard.matches(regex);
            System.out.println(idCard + " 是否有效: " + isValid);
        }
    }
}

提取数字
#

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class ExtractNumbers {
    public static void main(String[] args) {
        String text = "价格是100元,折扣是20%,总共120元";
        Pattern pattern = Pattern.compile("\\d+");
        Matcher matcher = pattern.matcher(text);
        
        System.out.println("提取的数字:");
        while (matcher.find()) {
            System.out.println(matcher.group());
        }
    }
}

十三、正则表达式练习题
#

练习题1:基本匹配
#

请编写代码,使用正则表达式匹配以下内容:

  1. 匹配所有数字
  2. 匹配所有字母
  3. 匹配所有单词(连续的字母)

参考答案:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class RegexExercise1 {
    public static void main(String[] args) {
        String text = "Hello123World456";
        
        // 1. 匹配所有数字
        Pattern pattern1 = Pattern.compile("\\d+");
        Matcher matcher1 = pattern1.matcher(text);
        System.out.println("数字:");
        while (matcher1.find()) {
            System.out.print(matcher1.group() + " ");
        }
        System.out.println();
        
        // 2. 匹配所有字母
        Pattern pattern2 = Pattern.compile("[a-zA-Z]");
        Matcher matcher2 = pattern2.matcher(text);
        System.out.println("字母:");
        while (matcher2.find()) {
            System.out.print(matcher2.group() + " ");
        }
        System.out.println();
        
        // 3. 匹配所有单词
        Pattern pattern3 = Pattern.compile("[a-zA-Z]+");
        Matcher matcher3 = pattern3.matcher(text);
        System.out.println("单词:");
        while (matcher3.find()) {
            System.out.print(matcher3.group() + " ");
        }
    }
}

练习题2:验证格式
#

请编写代码验证以下格式:

  1. 验证手机号(11位,1开头)
  2. 验证邮箱(简单格式)
  3. 验证日期格式(YYYY-MM-DD)

参考答案:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class RegexExercise2 {
    public static void main(String[] args) {
        // 1. 验证手机号
        String[] phones = {"13812345678", "12345678901", "1381234"};
        String phoneRegex = "1[3-9]\\d{9}";
        System.out.println("手机号验证:");
        for (String phone : phones) {
            System.out.println(phone + ": " + phone.matches(phoneRegex));
        }
        
        // 2. 验证邮箱
        String[] emails = {"user@example.com", "invalid.email", "test@domain"};
        String emailRegex = "[\\w.-]+@[\\w.-]+\\.[a-zA-Z]{2,}";
        System.out.println("\n邮箱验证:");
        for (String email : emails) {
            System.out.println(email + ": " + email.matches(emailRegex));
        }
        
        // 3. 验证日期
        String[] dates = {"2024-01-15", "2024-13-01", "24-01-15"};
        String dateRegex = "\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])";
        System.out.println("\n日期验证:");
        for (String date : dates) {
            System.out.println(date + ": " + date.matches(dateRegex));
        }
    }
}

练习题3:字符串替换
#

请使用正则表达式实现以下功能:

  1. 将字符串中的所有数字替换为"*"
  2. 将字符串中的多个连续空格替换为单个空格
  3. 提取字符串中的所有邮箱地址

参考答案:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class RegexExercise3 {
    public static void main(String[] args) {
        // 1. 替换所有数字
        String text1 = "价格是100元,折扣是20%";
        String result1 = text1.replaceAll("\\d+", "*");
        System.out.println("替换数字: " + result1);
        
        // 2. 替换多个空格为单个空格
        String text2 = "Hello    World    Java";
        String result2 = text2.replaceAll("\\s+", " ");
        System.out.println("替换空格: " + result2);
        
        // 3. 提取邮箱
        String text3 = "联系邮箱:user1@example.com 或 user2@test.org";
        Pattern pattern = Pattern.compile("[\\w.-]+@[\\w.-]+\\.[a-zA-Z]{2,}");
        Matcher matcher = pattern.matcher(text3);
        System.out.println("提取的邮箱:");
        while (matcher.find()) {
            System.out.println(matcher.group());
        }
    }
}

练习题4:分组提取
#

请编写代码,从字符串"2024-01-15"中提取年、月、日。

参考答案:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class RegexExercise4 {
    public static void main(String[] args) {
        String date = "2024-01-15";
        Pattern pattern = Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})");
        Matcher matcher = pattern.matcher(date);
        
        if (matcher.matches()) {
            System.out.println("年份: " + matcher.group(1));
            System.out.println("月份: " + matcher.group(2));
            System.out.println("日期: " + matcher.group(3));
        }
    }
}

练习题5:综合应用
#

请编写一个程序,实现以下功能:

  1. 验证输入的字符串是否为有效的IP地址(IPv4)
  2. 从文本中提取所有的URL链接
  3. 验证密码强度(至少8位,包含大小写字母、数字和特殊字符)

参考答案:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class RegexExercise5 {
    public static void main(String[] args) {
        // 1. 验证IP地址
        String[] ips = {"192.168.1.1", "256.1.1.1", "192.168.1"};
        String ipRegex = "((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)";
        System.out.println("IP地址验证:");
        for (String ip : ips) {
            System.out.println(ip + ": " + ip.matches(ipRegex));
        }
        
        // 2. 提取URL
        String text = "访问 https://www.example.com 或 http://test.org";
        Pattern urlPattern = Pattern.compile("https?://[\\w.-]+(?:/[\\w.-]*)*");
        Matcher urlMatcher = urlPattern.matcher(text);
        System.out.println("\n提取的URL:");
        while (urlMatcher.find()) {
            System.out.println(urlMatcher.group());
        }
        
        // 3. 验证密码强度
        String[] passwords = {"Abc123!@", "weak", "Strong123", "Strong123!"};
        // 至少8位,包含大小写字母、数字和特殊字符
        String passwordRegex = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$";
        System.out.println("\n密码强度验证:");
        for (String password : passwords) {
            System.out.println(password + ": " + password.matches(passwordRegex));
        }
    }
}

十四、正则表达式对比分析表
#

14.1 字符类对比
#

表达式等价表达式说明使用场景
.-任意字符(除换行)匹配任意字符
\d[0-9]数字匹配数字
\D[^0-9]非数字排除数字
\w[a-zA-Z0-9_]单词字符匹配字母数字下划线
\W[^a-zA-Z0-9_]非单词字符排除单词字符
\s[ \t\n\r\f]空白字符匹配空格、制表符等
\S[^ \t\n\r\f]非空白字符排除空白字符

14.2 量词对比
#

量词含义贪婪性示例匹配
*0次或多次贪婪a* 匹配 “aaa” 中的 “aaa”
*?0次或多次非贪婪a*? 匹配 “aaa” 中的 ""
+1次或多次贪婪a+ 匹配 “aaa” 中的 “aaa”
+?1次或多次非贪婪a+? 匹配 “aaa” 中的 “a”
?0次或1次贪婪a? 匹配 “a” 中的 “a”
??0次或1次非贪婪a?? 匹配 “a” 中的 ""
{n}恰好n次固定a{3} 匹配 “aaa”
{n,}至少n次贪婪a{2,} 匹配 “aaa” 中的 “aaa”
{n,m}n到m次贪婪a{2,3} 匹配 “aaa” 中的 “aaa”

14.3 Java正则表达式方法对比
#

方法功能返回值使用场景
matches()String判断整个字符串是否匹配boolean格式验证
find()Matcher查找下一个匹配boolean查找所有匹配
group()Matcher获取匹配的字符串String提取匹配内容
replaceAll()String替换所有匹配String批量替换
replaceFirst()String替换第一个匹配String单次替换
split()String按正则分割字符串String[]字符串分割

14.4 Pattern和Matcher使用对比
#

操作Pattern方式String方式性能灵活性
单次匹配Pattern.compile(regex).matcher(str).matches()str.matches(regex)String更快相同
多次匹配编译一次,多次使用每次重新编译Pattern更快Pattern更灵活
查找所有使用Matcher.find()无直接方法PatternPattern
分组提取使用Matcher.group()无直接方法PatternPattern
替换使用Matcher.replaceAll()String.replaceAll()相近相同

14.5 常用正则表达式模式
#

用途正则表达式说明
手机号1[3-9]\d{9}1开头,第二位3-9,共11位
邮箱[\w.-]+@[\w.-]+\.[a-zA-Z]{2,}简单邮箱格式
身份证\d{17}[\dXx]18位身份证号
日期\d{4}-\d{2}-\d{2}YYYY-MM-DD格式
IP地址((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)IPv4地址
URLhttps?://[\w.-]+(?:/[\w.-]*)*HTTP/HTTPS URL
中文[\u4e00-\u9fa5]+中文字符
密码强度^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$至少8位,包含大小写、数字、特殊字符

14.6 正则表达式性能优化建议
#

优化建议说明示例
预编译Pattern多次使用时编译一次Pattern pattern = Pattern.compile(regex);
使用非贪婪量词避免过度匹配.*? 代替 .*
使用字符类比选择符更高效[abc] 代替 (a|b|c)
避免回溯使用原子组或占有量词(?>...)++
简化表达式避免过度复杂简单表达式更高效
使用边界限制匹配范围\bword\b 代替 word