javaのクラスパスとかパッケージについて
『オラクル認定資格教科書 Javaプログラマ Gold SE 7 スピードマスター問題集 (EXAMPRESS)』
資格取ろうと勉強中なのですが、クラスパスについて理解していなかった
という衝撃の事実に気づかされました。
恥ずかしい。。。
環境
OS
OS X 10.10.5
実行環境
$ java -version java version "1.8.0_60" Java(TM) SE Runtime Environment (build 1.8.0_60-b27) Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)
コンパイラ
$ javac -version
javac 1.8.0_60
要点
- パッケージと同じ構造を持ったディレクトリにクラスファイルを配置する
- クラスパスに指定するパスはパッケージのルート
- パッケージに属しているクラスを実行するときはパッケージを含めて指定する
/root1/pack1/Test1.java
package pack1; import pack2.Test2; public class Test1 { public static void main(String[] args) { Test2 t2 = new Test2(); t2. printHoge(); } }
/root2/pack2/Test2.java
package pack2; public class Test2 { public void printHoge() { System.out.println("hoge"); } }
#カレントディレクトリはpack1 $ pwd /root1/pack1 #-classpathオプションでクラスパスを指定 #例ではTest1.javaとTest2.javaのパッケージのルートディレクトリを指定している #クラスパスを複数指定する場合は「:(コロン)」で区切る $ javac -classpath /root2/:.. Test1.java #確認 $ ls Test1.class Test1.java $ ls /root2/pack2 Test2.class Test2.java #ソースはTest1.javaを指定しているが、Test1の中でTest2を呼んでいるため、 #Test2のクラスパスの指定が必要。Test1のコンパイルと同時にTest2.javaもコンパイルされる
実行
#パッケージ指定されているクラスを実行する場合はパッケージ名を修飾する必要がある $ java -classpath /root2/:.. pack1.Test1 hoge
おまけ
ちなみに、パッケージのルートディレクトリがカレントディレクトリの場合、クラスパスの指定は必要ない。
これはクラスパスのデフォルトがカレントディレクトリだからである。
例えば、先ほどのソースファイルが以下のような配置である場合
/root/pack1/Test1.java
/root/pack2/Test2.java
#カレントディレクトリ確認 $ pwd /root #コンパイル $ javac pack1/Test1.java #実行 $ java pack1.Test1 hoge
のように、クラスパスを明示的に指定をせずコンパイル・実行ができる