目录

前言

一、Java正则的核心类

二、正则表达式基础语法速查

三、Java中的实战应用

1. 验证字符串(matches方法)

2. 查找内容(find与group方法)

3. 替换内容(replaceAll方法)

四、避坑指南与最佳实践

1. 转义字符的双重折磨

2. matches() vs find()

3. 性能优化:复用Pattern

五、常用元字符与预定义字符类

六、三大核心匹配模式

1.matches():全量匹配

2.find():查找匹配

3.lookingAt():前缀匹配

七、实战代码演示

八、常见坑点与解决方案

1. JDK 版本不兼容 (List.of 报错)

2. 贪婪 vs 非贪婪

九、总结


前言

正则表达式(Regular Expression,简称Regex)是处理字符串的利器。在Java中,通过java.util.regex包提供了强大的支持。无论你是要进行数据验证、文本替换还是复杂的内容提取,掌握正则表达式都是程序员的必备技能。

一、Java正则的核心类

在Java中,我们主要通过两个类来操作正则表达式:

1.java.util.regex.Pattern:正则表达式的编译表示。一个Pattern对象就是一个编译好的正则表达式,它是线程安全的,可以被多个线程共享。
2.java.util.regex.Matcher:匹配器。它负责解释Pattern对象,并对目标字符串进行匹配操作。

基本使用流程:

1.编译:将字符串形式的正则表达式编译成Pattern对象。
2.匹配:通过Pattern对象创建Matcher对象,并传入待匹配的字符串。
3.操作:调用Matcher的方法(如find(), matches(), group())进行匹配、查找或替换。

二、正则表达式基础语法速查

正则表达式由普通字符(如a-z)和元字符(有特殊含义的字符)组成。

常用元字符表

元字符描述示例
.匹配除换行符以外的任意字符a.c 匹配 "abc", "a2c"
^匹配字符串的开始^Hello 匹配以 "Hello" 开头的字符串
$匹配字符串的结束world$ 匹配以 "world" 结尾的字符串
*匹配前面的子表达式零次或多次ab*c 匹配 "ac", "abc", "abbbc"
+匹配前面的子表达式一次或多次ab+c 匹配 "abc", "abbbc",但不匹配 "ac"
?匹配前面的子表达式零次或一次ab?c 匹配 "ac", "abc"
{n}匹配前面的子表达式恰好n次a{3} 匹配 "aaa"
{n,}匹配前面的子表达式至少n次a{2,} 匹配 "aa", "aaa", ...
{n,m}匹配前面的子表达式至少n次,至多m次a{2,4} 匹配 "aa", "aaa", "aaaa"

常用预定义字符类

字符等价于描述
\d[0-9]匹配一个数字字符
\D[^0-9]匹配一个非数字字符
\w[a-zA-Z_0-9]匹配一个单词字符(字母、数字、下划线)
\W[^\w]匹配一个非单词字符
\s[\t\n\x0B\f\r]匹配一个空白字符(空格、制表符、换行等)
\S[^\s]匹配一个非空白字符

三、Java中的实战应用

1. 验证字符串(matches方法)

这是最常用的功能,比如验证手机号、邮箱、身份证等。
重要提示:String类的matches()方法会尝试匹配整个字符串。

// 验证手机号 (简单的11位数字)
String phone = "13800138000";
// 正则:以1开头,第二位是3-9,后面跟9位数字
String regex = "^1[3-9]\\d{9}$";
boolean isValid = phone.matches(regex);
System.out.println(isValid); // 输出: true

2. 查找内容(find与group方法)

如果你想在一段文本中提取所有符合规则的内容,需要用Pattern和Matcher。

String text = "联系方式:13800138000,备用电话:13912345678。";
String regex = "1[3-9]\\d{9}"; // 手机号正则
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);

while (matcher.find()) {
    // group() 返回匹配到的子字符串
    System.out.println("找到手机号: " + matcher.group());
}
// 输出:
// 找到手机号: 13800138000
// 找到手机号: 13912345678

3. 替换内容(replaceAll方法)

将文本中符合正则的部分替换成新的内容。

String text = "你的验证码是1234,请在5分钟内输入。";
// 将所有的数字替换为 *
String masked = text.replaceAll("\\d", "*");
System.out.println(masked);
// 输出: 你的验证码是****,请在*分钟内输入。

四、避坑指南与最佳实践

1. 转义字符的双重折磨

在Java字符串中,\本身就是一个转义字符。因此,要在Java代码中表示正则中的\d,你必须写成"\\d"。

1.正则:\d (匹配数字) -> Java字符串:"\\d"
2.正则:\. (匹配点号) -> Java字符串:"\\."

2. matches() vs find()

1.String.matches() / Matcher.matches():必须全匹配。如果正则只是字符串的一部分,它会返回false。
2.Matcher.find():部分匹配。只要在字符串中找到了符合正则的子串,就返回true。

3. 性能优化:复用Pattern

Pattern.compile()是一个相对耗时的操作。如果你的正则表达式是固定不变的(例如验证邮箱),建议将其定义为static final常量,以避免重复编译。

public class RegexUtils {
    // 预编译,提升性能
    private static final Pattern PHONE_PATTERN = Pattern.compile("^1[3-9]\\d{9}$");

    public static boolean isPhone(String input) {
        if (input == null) return false;
        return PHONE_PATTERN.matcher(input).matches();
    }
}

五、常用元字符与预定义字符类

在写代码之前,必须熟记这些“积木”。

表达式含义备注
\d匹配一个数字,等价于 [0-9]注意:Java字符串中需写成 "\\d"
\w匹配字母、数字或下划线,等价于 [a-zA-Z_0-9]"Word" 字符
\s匹配任意空白符,包括空格、制表符等"Space"
.匹配任意字符(换行符除外)
^匹配行的开始如 ^Hello
$匹配行的结束如 World$
*匹配 0 次或多次贪婪模式
+匹配 1 次或多次至少出现一次
?匹配 0 次或 1 次也可用于非贪婪模式修饰符
{n}匹配确定的 n 次如 \d{11} 匹配11位手机号
[]字符集合[abc] 匹配 a 或 b 或 c
``逻辑“或”

特别注意:

在 Java 代码中编写正则时,反斜杠 \ 本身是 Java 字符串的转义字符。因此,如果你想表示正则中的 \d,在 Java 字符串中必须写成 "\\d"。这就是为什么你在之前的截图中看到 String re = "\\d";。

六、三大核心匹配模式

Matcher 类提供了三种主要的匹配方法,它们的区别非常重要:

1.matches():全量匹配

1.含义:尝试将整个输入序列与模式进行匹配。
2.场景:表单验证(如验证手机号是否完全符合规则)。
3.例子:正则 \d+ 对字符串 123abc 使用 matches() 会返回 false,因为后面有字母。

2.find():查找匹配

1.含义:扫描输入序列,查找下一个匹配的子序列。
2.场景:爬虫提取数据、日志分析(在一长串文本中找特定的IP或日期)。
3.例子:正则 \d+ 对字符串 123abc456 使用 find(),第一次找到 123,第二次找到 456。

3.lookingAt():前缀匹配

1.含义:尝试从输入序列的开头开始匹配,但不要求匹配整个序列。
2.场景:较少用,用于判断字符串是否以某种特定模式开头。

七、实战代码演示

让我们通过一个完整的工具类来看看如何使用正则。

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexDemo {
    public static void main(String[] args) {
        // 1. 定义正则:匹配手机号(简单示例:1开头,第二位3-9,后面9位数字)
        // 注意:Java字符串中需要双反斜杠
        String regex = "^1[3-9]\\d{9}$";
        
        // 2. 编译正则表达式
        Pattern pattern = Pattern.compile(regex);
        
        // 3. 创建匹配器
        String phone = "13812345678";
        Matcher matcher = pattern.matcher(phone);
        
        // 4. 执行匹配
        if (matcher.matches()) {
            System.out.println(phone + " 是合法的手机号");
        } else {
            System.out.println(phone + " 格式错误");
        }
        
        // --- 进阶:提取内容 ---
        String text = "联系方式:13800138000,备用号:13900139000";
        String extractRegex = "1[3-9]\\d{9}"; // 去掉 ^ 和 $ 以便在文本中查找
        Matcher extractMatcher = Pattern.compile(extractRegex).matcher(text);
        
        System.out.println("开始提取手机号:");
        // 使用 while 循环配合 find() 提取所有匹配项
        while (extractMatcher.find()) {
            // group() 获取匹配到的字符串
            System.out.println("找到号码: " + extractMatcher.group());
        }
    }
}

八、常见坑点与解决方案

结合你之前的报错截图,这里有两个新手最容易踩的坑:

1. JDK 版本不兼容 (List.of 报错)

正如你在截图中遇到的 java: 找不到符号 错误:

原因:List.of() 是 Java 9 才引入的新特性。如果你的 IntelliJ IDEA 项目设置的是 Java 8(这是目前很多企业项目的标准),编译器就不认识这个方法。

解决:

1.方法A(推荐):升级项目的 JDK 版本到 11 或 17。
2.方法B(兼容写法):退回到 Java 8 的写法,使用 Arrays.asList:

// Java 9+ 写法
List.of("010-12345678", "020-99999999");

// Java 8 兼容写法
Arrays.asList("010-12345678", "020-99999999");

2. 贪婪 vs 非贪婪

1.贪婪模式(默认):正则表达式会尽可能多地匹配字符。
        例如:字符串 <a>hello</a><b>world</b>,使用正则 <.*>。
        结果:它会一次性匹配从第一个 < 到最后一个 > 的所有内容。
2.非贪婪模式:在量词后加 ?,尽可能少地匹配。
        例如:正则 <.*?>。
        结果:它会匹配到 </a> 就停止,分别得到 <a>hello</a> 和 <b>world</b>。

九、总结

正则表达式是 Java 开发中处理文本的“瑞士军刀”。
1.简单验证(如 String.matches())适合简单的逻辑。
2.复杂的提取和替换(如 Pattern + Matcher)适合处理大量数据。
3.务必注意 Java 转义字符(双反斜杠)和 JDK 版本 的兼容性。

希望这篇文章能帮你彻底搞懂 Java 正则!

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐