diff --git a/hutool-core/src/main/java/cn/hutool/core/util/PhoneUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/PhoneUtil.java
new file mode 100644
index 000000000..d88b2071d
--- /dev/null
+++ b/hutool-core/src/main/java/cn/hutool/core/util/PhoneUtil.java
@@ -0,0 +1,128 @@
+package cn.hutool.core.util;
+
+import cn.hutool.core.lang.Validator;
+
+import java.util.regex.Pattern;
+
+
+/**
+ * 手机号工具类
+ *
+ * @author dahuoyzs
+ */
+public class PhoneUtil {
+
+ /**
+ * 手机号码
+ */
+ private static Pattern MOBILE = Pattern.compile("(?:0|86|\\+86)?1[3456789]\\d{9}");
+ /**
+ * 座机号码
+ * */
+ private static Pattern TEL = Pattern.compile("0\\d{2,3}-[1-9]\\d{6,7}");
+ /**
+ * 座机号码+手机号码
+ * */
+ private static Pattern PHONE = Pattern.compile("^([0-9]{3}-?[0-9]{8})|dao([0-9]{4}-?[0-9]{7})$");
+
+ /**
+ * 验证是否为手机号码(中国)
+ *
+ * @param value 值
+ * @return 是否为手机号码(中国)
+ * @since 5.3.11
+ */
+ public static boolean isMobile(CharSequence value) {
+ return Validator.isMatchRegex(MOBILE, value);
+ }
+
+ /**
+ * 验证是否为座机号码(中国)
+ *
+ * @param value 值
+ * @return 是否为座机号码(中国)
+ * @since 5.3.11
+ */
+ public static boolean isTel(CharSequence value) {
+ return Validator.isMatchRegex(TEL, value);
+ }
+
+ /**
+ * 验证是否为座机号码+手机号码(中国)
+ *
+ * @param value 值
+ * @return 是否为座机号码+手机号码(中国)
+ * @since 5.3.11
+ */
+ public static boolean isPhone(CharSequence value) {
+ return Validator.isMatchRegex(PHONE, value);
+ }
+
+ /**
+ * 隐藏手机号前7位 替换字符为"*"
+ * 栗子
+ *
+ * @param phone 手机号码
+ * @return 替换后的字符串
+ * @since 5.3.11
+ */
+ public static CharSequence hideBefore(CharSequence phone){
+ return StrUtil.hide(phone,0,7);
+ }
+
+ /**
+ * 隐藏手机号中间4位 替换字符为"*"
+ *
+ * @param phone 手机号码
+ * @return 替换后的字符串
+ * @since 5.3.11
+ */
+ public static CharSequence hideBetween(CharSequence phone){
+ return StrUtil.hide(phone,3,7);
+ }
+
+ /**
+ * 隐藏手机号最后4位 替换字符为"*"
+ *
+ * @param phone 手机号码
+ * @return 替换后的字符串
+ * @since 5.3.11
+ */
+ public static CharSequence hideAfter(CharSequence phone){
+ return StrUtil.hide(phone,7,11);
+ }
+
+ /**
+ * 获取手机号前3位
+ *
+ * @param phone 手机号码
+ * @return 手机号前3位
+ * @since 5.3.11
+ */
+ public static CharSequence subBefore(CharSequence phone){
+ return StrUtil.sub(phone,0,3);
+ }
+
+ /**
+ * 获取手机号中间4位
+ *
+ * @param phone 手机号码
+ * @return 手机号中间4位
+ * @since 5.3.11
+ */
+ public static CharSequence subBetween(CharSequence phone){
+ return StrUtil.sub(phone,3,7);
+ }
+
+ /**
+ * 获取手机号后4位
+ *
+ * @param phone 手机号码
+ * @return 手机号后4位
+ * @since 5.3.11
+ */
+ public static CharSequence subAfter(CharSequence phone){
+ return StrUtil.sub(phone,7,11);
+ }
+
+}
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java
index 8e85bb7b3..d1d56ac1b 100644
--- a/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java
@@ -4043,6 +4043,32 @@ public class StrUtil {
return replace(str, startInclude, endExclude, '*');
}
+ /**
+ * 制定字符覆盖原字符串。
+ * 注意参数:
+ * StrUtil.hide()是 开始位置,到结束位置。
+ * StrUtil.cover()是 开始位置,指定长度。
+ *
+ * @param str 原字符串
+ * @param start 开始位置
+ * @param len 覆盖的长度
+ * @param character 覆盖的符号
+ * @return 返回值类型 符号覆盖字符后的字符串
+ * @since 5.3.11
+ * @author dahuoyzs
+ */
+ public CharSequence cover(String str,int start,int len,Character character){
+ if (start<0||len>str.length()){
+ throw new IndexOutOfBoundsException();
+ }
+ int end = start + len;
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < str.length(); i++) {
+ sb.append((start <= i && i < end) ? character : str.charAt(i));
+ }
+ return sb;
+ }
+
/**
* 替换字符字符数组中所有的字符为replacedStr
* 提供的chars为所有需要被替换的字符,例如:"\r\n",则"\r"和"\n"都会被替换,哪怕他们单独存在
diff --git a/hutool-core/src/test/java/cn/hutool/core/util/PhoneUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/PhoneUtilTest.java
new file mode 100644
index 000000000..c4451a5e1
--- /dev/null
+++ b/hutool-core/src/test/java/cn/hutool/core/util/PhoneUtilTest.java
@@ -0,0 +1,74 @@
+package cn.hutool.core.util;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.ArrayList;
+
+/**
+ * {@link PhoneUtil} 单元测试类
+ *
+ * @author dahuoyzs
+ *
+ */
+public class PhoneUtilTest {
+
+ @Test
+ public void testCheck(){
+ String mobile = "13612345678";
+ String tel = "010-88993108";
+ String errMobile = "136123456781";
+ String errTel = "010-889931081";
+
+ Assert.assertTrue(PhoneUtil.isMobile(mobile));
+ Assert.assertTrue(PhoneUtil.isTel(tel));
+ Assert.assertTrue(PhoneUtil.isPhone(mobile));
+ Assert.assertTrue(PhoneUtil.isPhone(tel));
+
+ Assert.assertFalse(PhoneUtil.isMobile(errMobile));
+ Assert.assertFalse(PhoneUtil.isTel(errTel));
+ Assert.assertFalse(PhoneUtil.isPhone(errMobile));
+ Assert.assertFalse(PhoneUtil.isPhone(errTel));
+ }
+
+ @Test
+ public void testTel(){
+ ArrayList tels = new ArrayList<>();
+ tels.add("010-12345678");
+ tels.add("020-9999999");
+ tels.add("0755-7654321");
+ ArrayList errTels = new ArrayList<>();
+ errTels.add("010 12345678");
+ errTels.add("A20-9999999");
+ errTels.add("0755-7654.321");
+ errTels.add("13619887123");
+ for (String s : tels) {
+ Assert.assertTrue(PhoneUtil.isTel(s));
+ }
+ for (String s : errTels) {
+ Assert.assertFalse(PhoneUtil.isTel(s));
+ }
+ }
+
+ @Test
+ public void testHide(){
+ String mobile = "13612345678";
+ String hideBefore = "*******5678";
+ String hideBetween = "136****5678";
+ String hideAfter = "1361234****";
+ Assert.assertEquals(PhoneUtil.hideBefore(mobile),hideBefore);
+ Assert.assertEquals(PhoneUtil.hideBetween(mobile),hideBetween);
+ Assert.assertEquals(PhoneUtil.hideAfter(mobile),hideAfter);
+ }
+
+ @Test
+ public void testSubString(){
+ String mobile = "13612345678";
+ String subBefore = "136";
+ String subBetween = "1234";
+ String subAfter = "5678";
+ Assert.assertEquals(PhoneUtil.subBefore(mobile),subBefore);
+ Assert.assertEquals(PhoneUtil.subBetween(mobile),subBetween);
+ Assert.assertEquals(PhoneUtil.subAfter(mobile),subAfter);
+ }
+}