javac如何自动编译一个class的依赖

How does javac automatically compile dependencies of a class

给定以下目录结构:

/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

为什么我们还没有编译 B.java 命令 javac -cp . pkg/A.java 就可以成功运行?

此外,如果当前目录是 /top/wrk/pkg,则命令 javac A.java 有效。为何如此?

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

查看您的输出目录,您会看到 B 也已编译。即使在不同的包中,它也会被编译,但你必须public才能从 A.

中引用它

Why does the command javac -cp . pkg/A.java work successfully even though we have not yet compiled B.java

当您编译 A.java 时,编译器也会编译 B.java,因为 A.javaB.java 都在同一个包中。即使 B.javaA.java 在不同的包中(前提是 B 是 public),只要这两个包都存在于 wrk 中,这也将起作用目录,然后从 wrk 目录编译 A.java

来自 Oracle documentation for javac :

If the -sourcepath option is not specified, the user class path is also searched for source files.

来自 Oracle document for CLASSPATH

The default value of the class path is "."

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

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

要确认 sourcepath 设置为 CLASSPATH,您可以尝试使用 -cp 选项通过编译 A.java 来更改 CLASSPATH javac -cp C:\ -verbose -g pkg\A.javaA.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

Also if the current directory is /top/wrk/pkg then the command javac A.java works. How so?

无论 B.class 是否存在于 pkg

中,这都不起作用

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

来自 Oracle javac docs...

If you set the -sourcepath option, then the compiler searches the indicated path for source files. Otherwise, the compiler searches the user class path for both class files and source files. On Windows, the -sourcepath option seems to be set by default and your command works.

不过在我的 Mac 上,它失败并给出以下消息...

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

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

javac -sourcepath ./* A.java