1. 概述
在这个教程中,我们将学习如何检查字符串是否包含非字母数字字符。这种功能在诸如密码强度检查、应用程序中限制特殊字符输入等场景中非常重要。当我们希望限制其仅用于特定语言脚本时,这个需求变得更有趣,这也是我们在这里尝试解决的问题。
2. 使用正则表达式
我们认为使用正则表达式是实现这一要求最灵活的方法。考虑一个简单的场景:应用只接受英文数字和字母字符。为此,我们可以使用正则表达式\[^a-zA-Z0-9\]
来识别非字母数字字符:
public class NonAlphaNumRegexChecker {
private static final Pattern PATTERN_NON_ALPHNUM_USASCII = Pattern.compile("[^a-zA-Z0-9]+");
public static boolean isAlphanumeric(String str) {
Matcher matcher = PATTERN_NON_ALPHNUM_USASCII.matcher(str);
return matcher.find();
}
}
但如果应用需要接受其他语言的字母,那么我们必须调整正则表达式,使其也涵盖Unicode字母和数字。更多详细信息,请参阅Javadocs中的“Unicode支持”部分:这里。这里我们使用了正则表达式的二进制属性类,如IsAlphabetic
和IsDigit
:
public class NonAlphaNumRegexChecker {
private static final Pattern PATTERN_NON_ALPHNUM_ANYLANG = Pattern.compile("[^\\p{IsAlphabetic}\\p{IsDigit}]");
public static boolean containsNonAlphanumeric(String input) {
Matcher matcher = PATTERN_NON_ALPHNUM_ANYLANG.matcher(input);
return matcher.find();
}
}
现在考虑另一个场景,应用只接受特定的Unicode脚本中的字符,比如西里尔字母、格鲁吉亚字母或希腊字母。为了实现这种情况,正则表达式支持如IsCyrillic
、IsGreek
、IsGeorgian
等Unicode脚本类。让我们看一个例子:
public class NonAlphaNumRegexChecker {
public static boolean containsNonAlphanumeric(String input, String script) {
String regexScriptClass = "\\p{" + "Is" + script + "}";
Pattern pattern = Pattern.compile("[^" + regexScriptClass + "\\p{IsDigit}]"); //Binary properties
Matcher matcher = pattern.matcher(input);
return matcher.find();
}
}
由于上述方法需要将语言脚本作为参数,每次调用时都需要编译模式,这可能会成为性能瓶颈。因此,我们可以缓存所有在枚举Character.UnicodeScript
(https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/Character.UnicodeScript.html)中提到的脚本对应的编译好的`Pattern`对象,并使用键`script`进行检索。
3. 使用Character
类的isLetterOrDigit()
方法
现在,让我们来看看Character
类的isLetterOrDigit()
方法,它可以帮助实现上一节讨论的所有用例。第一个解决方案通过isLetterOrDigit()
方法检查任何语言字符串中的非字母数字字符:
public class NonAlphaNumericChecker {
public static boolean isNonAlphanumericAnyLangScript(String str) {
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (!Character.isLetterOrDigit(c)) {
return true;
}
}
return false;
}
}
但是,如果我们只想允许特定语言脚本,我们需要稍作调整。这里,我们把一个字符视为非字母数字字符,当它既不是那种语言的字母也不是数字时:
public class NonAlphaNumericChecker {
public static boolean isNonAlphanumericInLangScript(String str, String script) {
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (!Character.UnicodeScript.of(c).toString().equalsIgnoreCase(script)
&& !Character.isDigit(c)) {
return true;
}
}
return false;
}
}
4. 使用Apache Commons Lang库的StringUtils
类
这是目前为止所有技术中最不灵活的一种。StringUtils
类的isAlphanumeric()
方法支持所有Unicode字母或数字,但没有提供识别字符串中使用的语言脚本的支持。让我们看看它是如何工作的:
public static boolean isNonAlphanumericAnyLangScriptV2(String str) {
return !StringUtils.isAlphanumeric(str);
}
5. 总结
在这个教程中,我们讨论了一些必须检查字符串中是否存在非字母数字字符的场景。结论是,正则表达式技术是所有可用选项中最灵活的。这里使用的代码片段,以及相关的JUnit测试用例,可以在GitHub上找到。