contains() 方法不接受 null 参数,否则抛出 NullPointerException;它基于 indexOf() 实现,区分大小写,空字符串返回 true;忽略大小写应使用 regionMatches() 而非 toLowerCase()。

contains() 方法只能用于 CharSequence,不能直接传 null
contains() 是 String 类的实例方法,底层调用 indexOf() 判断子串是否存在。它接收一个 CharSequence 参数(比如 String、StringBuilder),但**不接受 null**——传入会直接抛出 NullPointerException。
常见错误现象:str.contains(null) 运行时报错,而不是返回 false。
- 使用前务必检查参数是否为
null,例如:sub != null && str.contains(sub) - 如果子串可能为空字符串
"",放心用:"abc".contains("")返回true(Java 规定空串是任意字符串的子串) - 注意:该方法区分大小写,
"ABC".contains("abc")返回false
想忽略大小写?别用 contains(),改用 indexOf() + regionMatches()
contains() 没有忽略大小写的重载版本,强行转大小写(如 str.toLowerCase().contains(sub.toLowerCase()))看似简单,但存在两个隐患:
- 非 ASCII 字符(如德语
ß、土耳其语i/I)在不同 locale 下转换结果可能不一致 - 每次调用都新建字符串对象,影响性能,尤其在循环中频繁使用时
更稳妥的做法是用 String.indexOf() 配合 regionMatches():
立即学习“Java免费学习笔记(深入)”;
public static boolean containsIgnoreCase(String str, String sub) {
if (str == null || sub == null) return false;
int len = sub.length();
if (len == 0) return true;
for (int i = 0; i <= str.length() - len; i++) {
if (str.regionMatches(true, i, sub, 0, len)) {
return true;
}
}
return false;
}正则匹配需求?contains() 不适用,该换 Pattern 或 StringUtils
contains() 只做字面量子串匹配,不支持通配、边界、分组等正则能力。例如想判断字符串是否“以数字开头、后跟下划线和字母”,contains() 完全无能为力。
- 简单正则检查用
String.matches()或Pattern.compile().matcher().find() - 若已引入 Apache Commons Lang,
StringUtils.containsIgnoreCase()和StringUtils.containsAny()更省心 - 注意
matches()要求**整个字符串匹配**正则,查子串请用find(),否则容易误判
性能对比:contains() vs indexOf() >= 0
两者行为完全等价:str.contains(sub) 内部就是 str.indexOf(sub) >= 0。JDK 源码里它就是一层封装。
- 无需刻意替换为
indexOf()来“优化”——没有实际收益 - 但如果后续还需知道子串位置,直接用
indexOf()更高效,避免二次查找 - 对超长字符串且子串大概率不存在的场景,两者都基于朴素匹配(O(mn)),如需更高性能,考虑 KMP 或 Rabin-Karp 算法实现
字符串匹配看着简单,但 null 处理、大小写策略、编码边界、性能预期这些点,一不留神就在上线后冒出来。尤其是多语言环境下的 case-insensitive 判断,别图省事硬套 toLowerCase()。


















