contains()最常用但不支持null,需提前判空;indexOf()可获取位置信息,对空串返回0;正则匹配需转义元字符;StringUtils.contains()是null安全替代方案。

contains() 方法最常用,但要注意 null 安全
contains() 是判断子串存在的首选,它调用 indexOf() 内部实现,语义清晰、可读性强。但它不接受 null 参数——传入 null 会直接抛出 NullPointerException。
常见错误现象:str.contains(null) 或 str.contains(subStr) 中 subStr 未判空就调用。
- 使用前务必检查子串是否为
null,例如:subStr != null && str.contains(subStr) - 若需忽略大小写,不能直接用
contains(),得转成统一大小写再比较,如str.toLowerCase().contains(subStr.toLowerCase()) - 该方法区分 Unicode 码点,对代理对(surrogate pairs)支持正常,无需额外处理
indexOf() 返回值判断更底层,适合需要位置信息的场景
当不只是“有没有”,还需要“在哪儿”时,indexOf() 更合适。它返回首次匹配的索引,没找到则返回 -1,比布尔值多一层信息。
容易踩的坑:indexOf() 对空字符串 "" 总是返回 0,哪怕原字符串是 null(此时会 NPE)或空串本身。
立即学习“Java免费学习笔记(深入)”;
- 安全写法:
str != null && str.indexOf(subStr) >= 0 - 想查最后一次出现位置?换用
lastIndexOf() - 支持起始搜索位置参数,如
str.indexOf(subStr, fromIndex),可用于跳过前缀重复匹配
正则匹配 find() 需谨慎,避免过度设计
如果子串含正则元字符(如 .、*、?),又误用了 matches() 或 find(),结果会出人意料。例如 "a.b".matches("a.b") 实际匹配的是 a任意字符b,而非字面量 a.b。
真正想做字面量子串查找,别碰正则;真要正则能力,请用 Pattern.quote(subStr) 转义:
Pattern.compile(Pattern.quote(subStr)).matcher(str).find()
-
String.contains()永远按字面量匹配,更安全、更快 - 正则方案性能明显低于
contains()和indexOf(),尤其短字符串场景 -
matches()是全串匹配,不是子串查找,别混淆
StringUtils.contains() 可省去 null 判断,但要引入 Apache Commons
如果你已在项目中依赖 org.apache.commons.lang3.StringUtils,它的 contains() 是 null 安全的:传入 null 子串返回 false,传入 null 主串也返回 false,不会炸。
但注意:StringUtils.contains(null, "a") → false,而 "a".contains(null) → 抛异常,行为完全不同。
- 适合多处需判空的代码,能减少样板逻辑
- 不推荐仅为一个
contains引入整个 commons-lang3 - 它也不支持忽略大小写,仍需手动转大小写或改用
StringUtils.containsIgnoreCase()
str != null && subStr != null && str.contains(subStr) 就够了。复杂逻辑往往不是来自方法选错,而是没想清 null 怎么流、空字符串要不要算、大小写谁负责统一。










