
java 编译器(javac)在编译主类时会自动编译缺失的依赖类,但不会检测已存在 .class 文件是否过期;若源文件已修改而对应字节码未更新,将导致运行时行为异常。
java 编译器(javac)在编译主类时会自动编译缺失的依赖类,但不会检测已存在 .class 文件是否过期;若源文件已修改而对应字节码未更新,将导致运行时行为异常。
在 Java 项目中,javac 的编译行为遵循“按需依赖解析”原则:当你执行 javac GameLauncher.java 时,编译器会扫描其源码,发现对 GuessGame 类的引用;若当前目录下不存在 GuessGame.class,且存在 GuessGame.java,则 自动触发对该文件的编译——同理,GuessGame 中引用了 Player,若 Player.class 缺失但 Player.java 存在,也会被顺带编译。
然而,这一机制存在关键限制:javac 不做增量智能判断。例如:
- 若你先执行
javac GameLauncher.java,生成了GuessGame.class和Player.class; - 随后修改了
Player.java中的guess()方法(如返回new Random().nextInt(10)),但未重新编译; - 此时再次运行
java GameLauncher,程序仍加载旧的Player.class,导致始终返回0——这正是你观察到的现象。
✅ 正确做法示例:
# 方式1:显式编译全部源文件(适合小型项目) javac GameLauncher.java GuessGame.java Player.java # 方式2:使用通配符(确保无遗漏) javac *.java # 方式3:彻底清理后重编(推荐调试时使用) rm *.class javac GameLauncher.java
⚠️ 注意事项:
-
javac不会递归检查依赖类的修改时间,也不会构建依赖图谱; - 手动管理
.class文件易出错,尤其在多模块、跨包或含继承/泛型的复杂场景中; - 生产环境务必使用构建工具(如 Maven、Gradle),它们通过精确的依赖分析与时间戳比对,实现真正的增量编译。
总结:Java 编译器具备基础的“按需编译”能力,但不具备构建系统的智能感知力。理解这一边界,既能解释日常调试现象,也凸显了采用专业构建工具的必要性——它不是锦上添花,而是保障代码一致性与可维护性的基石。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











