java 6起支持classpath通配符*,专用于展开指定目录下所有.jar/.jar文件,不递归子目录、不匹配.class或非jar文件;需加英文引号包裹,跨平台分隔符不同,且加载顺序不确定。

Java 从 6 开始支持 classpath 中使用通配符 *,它不是匹配任意文件名的通用通配符,而是专用于自动展开目录下所有 .jar 和 .JAR 文件的语法糖。正确理解它的行为,能大幅简化命令行类路径配置,避免手动拼接大量 JAR 路径。
通配符 * 的真实含义
classpath 中的 * 表示“当前目录(或指定目录)下的所有 JAR 文件”,不包含子目录,也不匹配 .class 文件或其它后缀文件。
-
lib/*→ 展开为lib/a.jar:lib/b.jar:lib/c.jar(仅 lib 目录一级) -
*(单独写)→ 展开为当前目录下所有 .jar 文件,如app.jar:util.jar -
lib/*.jar→ 无效写法,Java 不识别这种带扩展名的通配形式;必须写成lib/* -
classes;classes/*→ 先加载 classes/ 下的 .class 文件,再加载 classes/ 下的全部 JAR;顺序影响类加载优先级
跨平台写法与引号要求
Windows 和 Unix/Linux 使用不同分隔符,且 必须用英文双引号包裹整个 classpath 字符串,否则 shell 或 cmd 会提前解析空格和 * 导致失败。
- Windows:
java -cp "lib/*;app.jar" com.Main(分号 ; 分隔) - Linux/macOS:
java -cp "lib/*:app.jar" com.Main(冒号 : 分隔) - 错误示范:
java -cp lib/*:app.jar com.Main→ shell 把 * 展开为文件列表,传给 java 的是乱序路径,且可能含空格导致截断
通配符不适用的常见场景
通配符虽方便,但有明确限制,误用会导致 ClassNotFoundException 或 NoClassDefFoundError。
- 不能递归搜索子目录:lib/common/* 不会包含 lib/common/utils/spring.jar,只找 lib/common/ 下的 JAR
-
不兼容 -jar 选项:一旦用了
java -jar app.jar,classpath 就由 MANIFEST.MF 的 Class-Path 指定,-cp参数被忽略 - 不匹配非 JAR 文件:lib/* 不会把 lib/config.properties 或 lib/log4j2.xml 加入 classpath(资源文件需确保在 JAR 内或显式添加目录)
- 加载顺序不确定:lib/* 展开后的 JAR 排序无保证,若多个 JAR 含同名类(如不同版本的 commons-lang),结果不可预测
替代方案:当通配符不够用时
遇到嵌套目录、需要精确控制顺序、或运行环境不支持 Java 6+(极少见),可用以下方式补位:
- Bash 下批量拼接:
java -cp "$(find lib -name '*.jar' | tr '\n' ':' | sed 's/:$//')" com.Main - PowerShell(Windows):
java -cp "$((Get-ChildItem lib\*.jar | ForEach-Object { $_.FullName }) -join ';')" com.Main - 构建工具中统一管理:Maven 的
mvn exec:java或 Gradle 的javaExec自动处理依赖 classpath,无需手写











