在 Java 中,判断一个字符串是否不包含另一个子字符串,通常有以下几种常用方法,核心思想是先判断“包含”,然后取反。

使用 String.indexOf() (最经典、最常用)
indexOf() 方法会查找子字符串在父字符串中第一次出现的位置的索引,如果找到,返回索引值(从0开始);如果找不到,则返回 -1。
要判断“不包含”,只需检查 indexOf() 的返回值是否为 -1 即可。
public class StringNotContainsExample {
public static void main(String[] args) {
String mainString = "Hello, welcome to the world of Java programming.";
String substring1 = "Python"; // 不包含的字符串
String substring2 = "Java"; // 包含的字符串
// 判断 mainString 是否不包含 substring1
boolean doesNotContain1 = mainString.indexOf(substring1) == -1;
System.out.println("字符串是否不包含 'Python'? " + doesNotContain1); // 输出: true
// 判断 mainString 是否不包含 substring2
boolean doesNotContain2 = mainString.indexOf(substring2) == -1;
System.out.println("字符串是否不包含 'Java'? " + doesNotContain2); // 输出: false
}
}
优点:
- 简单直观,是 Java 早期版本就存在的方法,兼容性最好。
- 性能通常很好,是底层实现最直接的方式之一。
使用 String.contains() (最语义化、最推荐)
Java 1.5 引入了 contains() 方法,它的返回值是一个 boolean 类型,直接表示字符串是否包含指定的 CharSequence(字符序列,如 String)。

要判断“不包含”,只需对 contains() 的结果取反(使用逻辑非运算符 )。
public class StringNotContainsExample {
public static void main(String[] args) {
String mainString = "Hello, welcome to the world of Java programming.";
String substring1 = "Python"; // 不包含的字符串
String substring2 = "Java"; // 包含的字符串
// 判断 mainString 是否不包含 substring1
boolean doesNotContain1 = !mainString.contains(substring1);
System.out.println("字符串是否不包含 'Python'? " + doesNotContain1); // 输出: true
// 判断 mainString 是否不包含 substring2
boolean doesNotContain2 = !mainString.contains(substring2);
System.out.println("字符串是否不包含 'Java'? " + doesNotContain2); // 输出: false
}
}
优点:
- 代码可读性最高。
!str.contains("...")的意图非常明确,不包含”。 - 是现代 Java 编程的推荐做法。
使用 String.matches() 和正则表达式 (功能最强大)
matches() 方法使用正则表达式来匹配整个字符串,如果想让字符串从头到尾都不包含某个子串,可以使用正则表达式中的“否定先行断言”(Negative Lookahead)。
注意: 这种方法性能开销最大,仅在需要复杂匹配逻辑时使用。

public class StringNotContainsExample {
public static void main(String[] args) {
String mainString = "Hello, welcome to the world of Java programming.";
String substring1 = "Python";
String substring2 = "Java";
// 正则表达式:^(?!.*Python).*$
// ^ : 字符串开始
// (?!.*Python) : 否定先行断言,确保从当前位置开始,后面任意位置(.*)都没有 "Python"
// .* : 匹配任意字符(除换行符)零次或多次
// $ : 字符串结束
boolean doesNotContain1 = mainString.matches("^(?!.*" + substring1 + ").*$");
System.out.println("字符串是否不包含 'Python'? " + doesNotContain1); // 输出: true
boolean doesNotContain2 = mainString.matches("^(?!.*" + substring2 + ").*$");
System.out.println("字符串是否不包含 'Java'? " + doesNotContain2); // 输出: false
}
}
优点:
- 功能极其强大,可以处理非常复杂的“不包含”逻辑,不包含A或B”、“不包含A但包含B”等。
- 适用于需要结合正则表达式的场景。
缺点:
- 语法复杂,可读性差。
- 性能远低于前两种方法,因为它需要编译和执行正则表达式引擎。
总结与推荐
| 方法 | 代码示例 | 可读性 | 性能 | 适用场景 |
|---|---|---|---|---|
indexOf() |
str.indexOf(sub) == -1 |
良好 | 高 | 兼容旧代码,或在不使用 boolean 返回值的逻辑中。 |
contains() |
!str.contains(sub) |
极佳 | 高 | 强烈推荐,绝大多数场景下的首选,代码最清晰。 |
matches() |
str.matches("^(?!.*sub).*$") |
差 | 低 | 仅当需要结合复杂正则表达式时使用。 |
最佳实践
在日常开发中,强烈推荐使用 !str.contains(sub),因为它既高效又清晰地表达了你的意图。
示例:在 if 语句中的使用
String filename = "report_final.pdf";
String forbiddenWord = "secret";
if (!filename.contains(forbiddenWord)) {
System.out.println("文件名安全,可以处理。");
} else {
System.out.println("文件名包含敏感词,禁止处理!");
}
// 输出: 文件名安全,可以处理。 