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

给定以下目录结构:

/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.java 即使我们还没有编译B.java javac -cp . pkg/A.java能成功B.java

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

为什么命令javac -cp。 即使我们还没有编译B.java,pkg / A.java也能成功运行

编译A.java ,编译器也将编译B.java ,因为A.javaB.java都在同一个包中。 即使B.javaA.java位于不同的包中(假设B是公共的),只要两个包都存在于A.java目录中并且从A.java目录编译A.java ,这将是有效的。

来自javac的Oracle文档 :

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

从Oracle文档中获取CLASSPATH

类路径的默认值是“。”

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

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

要确认sourcepath设置为CLASSPATH ,可以尝试使用A.java选项通过使用javac -cp C:\ -verbose -g pkg\A.java编译A.java来更改CLASSPATHA.java不会编译,因为你已经将CLASSPATH覆盖到C:\ ,这也是默认的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.class是否存在于pkg这都不起作用

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

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

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

来自Oracle javac文档 …

如果设置-sourcepath选项,则编译器将在指示的路径中搜索源文件。 否则,编译器将在用户类路径中搜索类文件和源文件。 在Windows上,-sourcepath选项似乎默认设置,您的命令可以正常工作。

但是在我的Mac上,它失败并给出以下消息……

 A.java:5: error: cannot find symbol B b; ^ symbol: class B location: class A 1 error 

要使其自动查找和编译依赖项的源文件,您需要使用-sourcepath选项。 例如..

  javac -sourcepath ./* A.java