web-dev-qa-db-ja.com

javacはどのようにしてクラスの依存関係を自動的にコンパイルしますか

次のディレクトリ構造が与えられます。

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

2つのファイル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が正常に機能するのはなぜですか?

また、現在のディレクトリが/top/wrk/pkgの場合、コマンドjavac A.Javaが機能します。どうして?

14
paidedly

コマンドjavac-cpを使用するのはなぜですか。 pkg/A.Javaは、B.Javaをまだコンパイルしていなくても、正常に動作します。

A.Javaをコンパイルすると、B.JavaA.Javaの両方が同じパッケージに含まれているため、コンパイラはB.Javaもコンパイルします。これは、B.JavaA.Javaとは異なるパッケージに含まれていても(Bがパブリックである場合)、両方のパッケージがwrkディレクトリに存在している限り機能します。 wrkディレクトリからA.Javaをコンパイルします。

Oracleドキュメント for javacから:

-sourcepathオプションが指定されていない場合、ユーザークラスパスでもソースファイルが検索されます。

Oracleドキュメント for CLASSPATHから

クラスパスのデフォルト値は「。」です。

CLASSPATHを設定していない場合、デフォルトで.になります。その後、デフォルトのsourcepathsourcepathと同じであるため、CLASSPATH.になります。 .を使用してA.Javaをコンパイルすると、デフォルトのソースパスがjavac -verbose -g pkg\A.Javaに設定されていることを確認できます。コンパイラが現在のディレクトリで.Javaファイルを探していることに注意してください。

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

sourcepathCLASSPATHに設定されていることを確認するには、-cpを使用してA.Javaをコンパイルし、javac -cp C:\ -verbose -g pkg\A.Javaオプションを使用してCLASSPATHを変更してみてください。 ] _。 CLASSPATHA.Javaに上書きしたため、今回は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の場合、コマンドjavacA.Javaが機能します。どうして?

これは、B.classpkgに存在するかどうかに関係なく機能しません。

免責事項:この動作はWindowsでしか確認できませんが、他のオペレーティングシステムでは異なるはずだと強く疑っています。

9
CKing

Oracle javac docs ..から.

-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
1
Phil Anderson

コンパイラーは、Bのソースを見つけて正常にコンパイルするか、単なるインポートであってもBの.classを見つける必要があります。動的に行われるロードとは対照的です。

出力ディレクトリを見ると、Bもコンパイルされていることがわかります。別のパッケージであってもコンパイルされますが、Aから参照するには公開する必要があります。

1
vempo