javac如何自动编译类的依赖关系

2022-09-03 15:15:09

给定以下目录结构:

/top
   |--- wrk
          |--- pkg
                  |--- A.java
                  |--- B.java

假定这两个文件和包含以下代码,分别:A.javaB.java

// Filename: A.java
package pkg;
class A { B b; }

// Filename: B.java
package pkg;
class B {...}

假设当前目录为/top/wrk

为什么即使我们尚未编译,该命令也能成功工作?javac -cp . pkg/A.javaB.java

此外,如果当前目录是,则该命令有效。怎么会这样?/top/wrk/pkgjavac A.java


答案 1

为什么命令 javac -cp .pkg/A.java成功工作,即使我们还没有编译B.java

当你编译时,编译器也会编译,因为两者都在同一个包中。即使与(前提是公共)位于不同的包中,只要两个包都存在于目录中并且您从目录中编译,这也有效。A.javaB.javaA.javaB.javaB.javaA.javaBwrkA.javawrk

摘自 Oracle 文档::javac

如果未指定 -sourcepath 选项,则还会在用户类路径中搜索源文件。

甲骨文文档中CLASSPATH

类路径的默认值为“.”

如果尚未设置 ,则默认为 。随后,也将是,因为默认值与 相同。您可以通过使用 进行编译来确认默认源路径是否设置为 。请注意,编译器正在当前目录中查找文件:CLASSPATH.sourcepath.sourcepathCLASSPATH.A.javajavac -verbose -g pkg\A.java.java

[parsing started pkg\A.java] [parsing completed 29ms] [search path for source files: [.]]

要确认 设置为 ,可以尝试通过使用 进行编译来更改 using 选项。 这次不会编译,因为你已经覆盖了 to,这也是默认的。这是输出:sourcepathCLASSPATHCLASSPATH-cpA.javajavac -cp C:\ -verbose -g pkg\A.javaA.javaCLASSPATHC:\sourcepath

[parsing started pkg\A.java] [parsing completed 26ms] [search path for source files: [C:\]] pkg\A.java:3: cannot find symbol symbol : class B

此外,如果当前目录是 /top/wrk/pkg,则命令 javac A.java 工作正常。怎么会这样?

无论是否存在于B.classpkg

免責聲明:我只能在Windows上确认此行为,但我非常怀疑在其他操作系统上应该有任何不同。


答案 2

编译器必须查找并成功编译 B 的源代码,或者查找 B 的.class,即使它只是一个导入。与加载相反,加载是动态完成的。

查看输出目录,您会看到 B 也已编译。即使它位于不同的包中,它也会被编译,但您必须将其公开才能从A引用它。