首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 手機號碼正則驗證完整指南:三大運營商號段精準匹配

     編輯:Java 相關知識

手機號驗證是表單校驗、用戶註冊、短信發送等場景的高頻需求。中國大陸手機號遵循「11 位數字、首位 1、第二位 3-9、第三位依運營商規則」的結構。本文提供生產就緒的正則模式,涵蓋通用、移動、聯通、電信、固話/小靈通五大場景。

核心正則常量介面

public interface RegexpConst {
    /** 通用手機號:三大運營商全覆蓋 */
    String MOBILE = "^1(3[0-9]|5[0-35-9]|8[025-9])\\d{8}$";

    /** 中國移動:134-139、147、150-152、157-159、172、178、182-184、187-188、198 */
    String CM = "^1(34[0-8]|(3[5-9]|5[017-9]|8[23478])\\d)\\d{7}$";

    /** 中國聯通:130-132、145、155、156、166、171、175、176、185、186、196 */
    String CU = "^1(3[0-2]|5[56]|8[56])\\d{8}$";

    /** 中國電信:133、149、153、173、177、180、181、189、199 */
    String CT = "^1((33|53|8[019])[0-9]|349|7[37])\\d{7}$";

    /** 固話/小靈通:區號 3-4 位 (010/021/0xxx) + 號碼 7-8 位 */
    String PHS = "^0(10|2[0-5789]|\\d{3})\\d{7,8}$";
}

正則結構深度解析

通用手機號 MOBILE

^1              # 首位固定 1
(               # 第二、三位分組
  3[0-9]        # 130-139 全段
| 5[0-35-9]     # 150-153, 155-159 (排除 154)
| 8[025-9]      # 180, 182-189 (排除 181)
)
\\d{8}$         # 後 8 位任意數字

覆蓋率:包含 13x、15x、18x 全段,以及 147、176、177、181、189、191、198、199 等新號段 (視具體版本)。建議定期同步工信部最新號段資料更新正則。

運營商專屬正則

運營商核心號段 (第二、三位)正則關鍵部分
移動134-139, 147, 150-152, 157-159, 172, 178, 182-184, 187-188, 19834[0-8]|(3[5-9]|5[017-9]|8[23478])
聯通130-132, 145, 155-156, 166, 171, 175-176, 185-186, 1963[0-2]|5[56]|8[56]
電信133, 149, 153, 173, 177, 180-181, 189, 199(33|53|8[019])|349|7[37]

工具類實作與單元測試

import java.util.regex.Pattern;

public class MobileValidator {
    private static final Pattern MOBILE_PATTERN = Pattern.compile(RegexpConst.MOBILE);
    private static final Pattern CM_PATTERN = Pattern.compile(RegexpConst.CM);
    private static final Pattern CU_PATTERN = Pattern.compile(RegexpConst.CU);
    private static final Pattern CT_PATTERN = Pattern.compile(RegexpConst.CT);
    private static final Pattern PHS_PATTERN = Pattern.compile(RegexpConst.PHS);

    /** 靜態編譯 Pattern,效能最佳 */
    public static boolean isMobile(String phone) {
        return phone != null && MOBILE_PATTERN.matcher(phone).matches();
    }

    public static boolean isChinaMobile(String phone) {
        return phone != null && CM_PATTERN.matcher(phone).matches();
    }

    public static boolean isChinaUnicom(String phone) {
        return phone != null && CU_PATTERN.matcher(phone).matches();
    }

    public static boolean isChinaTelecom(String phone) {
        return phone != null && CT_PATTERN.matcher(phone).matches();
    }

    public static boolean isLandline(String phone) {
        return phone != null && PHS_PATTERN.matcher(phone).matches();
    }

    /** 識別運營商類型 */
    public static String getCarrier(String phone) {
        if (!isMobile(phone)) return "UNKNOWN";
        if (isChinaMobile(phone)) return "CHINA_MOBILE";
        if (isChinaUnicom(phone)) return "CHINA_UNICOM";
        if (isChinaTelecom(phone)) return "CHINA_TELECOM";
        return "OTHER";
    }
}

JUnit 5 測試用例

@Test
void testMobileValidation() {
    // 正向用例
    assertTrue(MobileValidator.isMobile("13800138000"));
    assertTrue(MobileValidator.isMobile("15912345678"));
    assertTrue(MobileValidator.isMobile("18612345678"));
    assertEquals("CHINA_MOBILE", MobileValidator.getCarrier("13900000000"));
    assertEquals("CHINA_UNICOM", MobileValidator.getCarrier("13100000000"));
    assertEquals("CHINA_TELECOM", MobileValidator.getCarrier("13300000000"));

    // 反向用例
    assertFalse(MobileValidator.isMobile("12800138000")); // 第二位不合法
    assertFalse(MobileValidator.isMobile("1380013800"));  // 10 位
    assertFalse(MobileValidator.isMobile("138001380000")); // 12 位
    assertFalse(MobileValidator.isMobile("abc"));         // 非數字
    assertNull(MobileValidator.isMobile(null));           // null 安全
}

生產環境避坑指南

  1. 編譯 Pattern 為靜態常量:避免每次驗證重複編譯正則,效能提升 10-100 倍。
  2. 前端/網關雙重驗證:前端攔截明顯錯誤 (長度、非數字),後端做精準正則校驗,防繞過。
  3. 定期更新號段:工信部每年分配新號段 (如 16x、17x、19x 物聯網/虛擬運營商號段),建議半年同步一次最新號段庫更新正則。
  4. 國際化場景:海外手機號格式差異極大,建議引入 libphonenumber (Google 開源庫) 替代手寫正則。
  5. 虛擬運營商/物聯網卡:170、171、165、146 等號段歸屬複雜,若業務需區分真實運營商,需查詢號段歸屬資料庫而非單純正則。

擴展:libphonenumber 企業級方案

<dependency>
    <groupId>com.googlecode.libphonenumber</groupId>
    <artifactId>libphonenumber</artifactId>
    <version>8.13.0</version>
</dependency>

// 使用示例
PhoneNumberUtil util = PhoneNumberUtil.getInstance();
Phonenumber.PhoneNumber pn = util.parse("13800138000", "CN");
boolean valid = util.isValidNumber(pn); // true
String formatted = util.format(pn, PhoneNumberFormat.E164); // +8613800138000

支援 200+ 國家/地區、號碼類型識別 (行動/固話/免費/付費/VoIP)、格式化、地理位置推斷,是國際化產品的標準選擇。

正則驗證雖簡單,但號段演進快、邊界情況多,建立可維護的驗證體系 (常量管理、靜態編譯、單元測試、定期更新機制) 才是長久之計。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved