次のディレクトリ構造が与えられます。
/top
|--- wrk
|--- pkg
|--- A.Java
|--- B.Java
2つのファイルA.Java
とB.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
が機能します。どうして?
コマンドjavac-cpを使用するのはなぜですか。 pkg/A.Javaは、B.Javaをまだコンパイルしていなくても、正常に動作します。
A.Java
をコンパイルすると、B.Java
とA.Java
の両方が同じパッケージに含まれているため、コンパイラはB.Java
もコンパイルします。これは、B.Java
がA.Java
とは異なるパッケージに含まれていても(B
がパブリックである場合)、両方のパッケージがwrk
ディレクトリに存在している限り機能します。 wrk
ディレクトリからA.Java
をコンパイルします。
Oracleドキュメント for javac
から:
-sourcepathオプションが指定されていない場合、ユーザークラスパスでもソースファイルが検索されます。
Oracleドキュメント for CLASSPATH
から
クラスパスのデフォルト値は「。」です。
CLASSPATH
を設定していない場合、デフォルトで.
になります。その後、デフォルトのsourcepath
はsourcepath
と同じであるため、CLASSPATH
も.
になります。 .
を使用してA.Java
をコンパイルすると、デフォルトのソースパスがjavac -verbose -g pkg\A.Java
に設定されていることを確認できます。コンパイラが現在のディレクトリで.Java
ファイルを探していることに注意してください。
[parsing started pkg\A.Java] [parsing completed 29ms] [search path for source files: [.]]
sourcepath
がCLASSPATH
に設定されていることを確認するには、-cp
を使用してA.Java
をコンパイルし、javac -cp C:\ -verbose -g pkg\A.Java
オプションを使用してCLASSPATH
を変更してみてください。 ] _。 CLASSPATH
をA.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.class
がpkg
に存在するかどうかに関係なく機能しません。
免責事項:この動作はWindowsでしか確認できませんが、他のオペレーティングシステムでは異なるはずだと強く疑っています。
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
コンパイラーは、Bのソースを見つけて正常にコンパイルするか、単なるインポートであってもBの.classを見つける必要があります。動的に行われるロードとは対照的です。
出力ディレクトリを見ると、Bもコンパイルされていることがわかります。別のパッケージであってもコンパイルされますが、Aから参照するには公開する必要があります。