2. 使用文件名编译
假设当前目录下有两个目录:src
(存放Java源文件)和out
(存放编译后的class文件)。我们先看一个简单场景:src
目录中只有一个Java文件com/baeldung/MyClass.java
。
$ javac -d ./out/ ./src/com/baeldung/MyClass.java
这里-d
选项指定class文件的输出目录。注意MyClass.java
的具体代码内容不重要,只需确保语法正确即可。
当项目文件增多时,比如新增三个文件YourClass.java
、HerClass.java
和HisClass.java
,我们可以手动列出所有文件:
$ javac -d ./out/ \
./src/com/baeldung/MyClass.java \
./src/com/baeldung/YourClass.java \
./src/com/baeldung/HerClass.java \
./src/com/baeldung/HisClass.java
如果存在一个主类(如Main.java
)引用了其他类,只需编译主类即可:
$ javac -sourcepath ./src/ -d ./out/ ./src/com/baeldung/Main.java
此时javac
会自动查找并编译依赖的类文件。若需禁用自动编译依赖类,可添加-implicit:none
选项。-sourcepath
选项告诉编译器源文件的位置,也可用-classpath
或-cp
替代:
$ javac -cp ./src/ -d ./out/ ./src/com/baeldung/Main.java
但这种方法有局限:只编译被引用的类。例如新增一个ItsClass.java
但未被Main.java
引用,该文件就不会被编译。
适用场景:
- 源文件数量极少时
- 存在递归引用所有类的主入口类时
3. 使用通配符编译
javac
支持通配符*
编译同目录下的多个文件:
$ javac -d ./out/ ./src/com/baeldung/*.java
当项目包含子包时(如新增spring
、summer
、autumn
、winter
四个子包),可分别指定通配符:
$ javac -d ./out/ \
./src/com/baeldung/*.java \
./src/com/baeldung/spring/*.java \
./src/com/baeldung/summer/*.java \
./src/com/baeldung/autumn/*.java \
./src/com/baeldung/winter/*.java
适用场景:包数量较少时(无论源文件多少)
4. 使用参数文件编译
当包数量较多时,参数文件(可包含选项和源文件名)是更优雅的解决方案。使用@
前缀指定参数文件:
$ javac -d ./out/ @sources.txt
生成sources.txt
的方法因操作系统而异:
- Linux/macOS:使用
find
命令$ find ./src/ -type f -name "*.java" > sources.txt
- Windows:使用
dir
命令> dir src /b /s *.java > sources.txt
注意:每次增删源文件后需重新生成sources.txt
。
5. 其他进阶方法
5.1 使用Globstar(Bash 4.0+)
Bash 4.0引入了globstar
选项,使双通配符**
能递归匹配多级目录。默认关闭,需手动启用:
# 查看当前状态
$ shopt globstar
globstar off
# 启用globstar
$ shopt -s globstar
# 编译所有Java文件
$ javac -d ./out/ ./src/**/*.java
# 禁用globstar
$ shopt -u globstar
5.2 使用管道(Pipe)
通过管道组合命令实现编译:
- xargs方式:
$ find ./src/ -type f -name "*.java" | xargs javac -cp ./src/ -d ./out/
- find的-exec方式(性能优化):
# 基础版(慢,每个文件启动一次javac) $ find ./src/ -type f -name "*.java" -exec javac -cp ./src/ -d ./out/ '{}' ';' # 优化版(快,批量执行) $ find ./src/ -type f -name "*.java" -exec javac -cp ./src/ -d ./out/ '{}' +
性能提示:将分号
;
替换为加号+
可显著提升编译速度(减少javac启动次数)。
6. 总结
本文介绍了多种编译目录结构中Java源文件的方法:
- 基础方法:文件名列表(适合少量文件)、通配符(适合少量包)
- 高效方法:参数文件(需维护文件列表)、Globstar(Bash专属)、管道(跨平台)
- 踩坑提示:手动指定文件名会遗漏未引用类;参数文件需动态更新;
find -exec
用分号执行效率低下
根据项目规模和操作系统特性选择合适方案,在没有构建工具的特殊场景下,这些技巧能帮你高效完成编译任务。