分割コンパイル
Javaではパブリックのクラスは、クラス名と同じ名前のファイルにひとつ定義できる。すなわち、複数のクラスを定義するときには複数のファイルから構成される。
複数のソースコードをバラバラにコンパイルすることは、一般的に分割コンパイルと呼ばれる。
例
Person.java
public class Person {
private int age;
private String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public void printName() {
System.out.println(this.name);
}
public void printAge() {
System.out.println(this.age);
}
}
TestApp.java
public class TestApp {
public static void main(String[] args) {
Person p = new Person(20, "John Doe");
p.printName();
p.printAge();
}
}
TestApp.javaにて、Person クラスを利用している。
TestApp.javaをコンパイルすると、TestApp.classのほかに、自動的にPerson.javaもコンパイルされPerson.classが作成される。
javacでは必要に応じて、クラスを探して利用したり、関連ファイルをコンパイルし直す。クラスを探すときは、クラスパスとして指定されたパスを探す。指定が無い場合は . (カレントディレクトリ) を探す。
クラスパスは環境変数CLASSPATHで指定する。
export CLASSPATH=.:./dir1
: で区切り、 . と ./dir1 サブディレクトリを追加している。
パッケージ
Javaではクラスを整理するために、通常パッケージを利用する。パッケージはクラス名を階層構造に整理し、パッケージ名は通常インターネットドメインを逆にした形式となる。
例
サブディレクトリmypackage内にPerson.javaを保存する。Person.javaではpackage文を用いて、パッケージ mypackage内にあることを明示する。
package mypackage;
public class Person {
private int age;
private String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public void printName() {
System.out.println(this.name);
}
public void printAge() {
System.out.println(this.age);
}
}
パッケージ内のクラスを利用する側であるTestApp.javaでは、import文を使って利用するクラス名を指定する。
ソースコードでimport mypackage.Personと記述すれば、Personとして mypackage.Personクラスが使える。
import mypackage.Person;
public class TestApp {
public static void main(String[] args) {
Person p = new Person(20, "John Doe");
p.printName();
p.printAge();
}
}
パッケージ内に複数のクラスがあり、全てを取り込む場合は、import mypackage.*;というようにワイルドカードを使うこともできる。
コンパイル時のソースパスとクラスファイル出力先を指定する
パッケージを使ってファイルを整理すると、 ソースツリーの階層構造が深くなりがちであり、デフォルトの設定では同じディレクトリ内にクラスファイルが生成されるため、生成されるクラスファイルもあちこちに散らばってしまう。
ソースファイルとクラスファイルは、それぞれ別のディレクトリツリーとしたほうが管理が簡単なことが多い。
例
tree
.
└── src
└── com
└── keicode
├── TestApp.java
└── models
└── Person.java
4 directories, 2 files
コンパイルするには、src ディレクトリにて、
javac ./com/keicode/TestApp.java
とする。
もしsrcディレクトリの親ディレクトリで実行するなら、-sourcepathオプションを指定する。
javac -sourcepath src src/com/keicode/TestApp.java
コンパイルの結果、*.classファイルは、*.javaファイルと同じディレクトリに保存される。
-dオプションを使うと、クラスファイルを出力するディレクトリを指定することができる。
javac -d out -sourcepath src src/com/keicode/TestApp.java
結果は以下の通り。
tree
.
├── out
│ └── com
│ └── keicode
│ ├── TestApp.class
│ └── models
│ └── Person.class
└── src
└── com
└── keicode
├── TestApp.java
└── models
└── Person.java
8 directories, 4 files
JARファイルの作成
一つのプログラムを一つのファイルにまとめるには、Javaアーカイブ(JAR ファイル, *.jar)として、ひとつのファイルにパッケージする。
JARファイルは、jarコマンドにより作成される。
jar cfe TestApp.jar TestApp *.class ./mypackage/*.class
この結果、TestApp.jarが作成される。
cf:ファイルを作成 (create file)。ファイル名を直後に指定。
e:エントリーポイント (プログラムの開始場所) を指定する。アーカイブの中には複数の Javaクラスを指定することが可能だが、その中でプログラムの開始地点となるクラスのmain関数がエントリーポイントと呼ばれる。
エントリーポイントとなるmain関数を含むクラスはメインクラスと呼ばれ、jarファイルの中に作成されるマニフェストファイル(MANIFEST.MF)に記録される。
最後のパラメータは jarファイルに含むclassファイルのリストで、ワイルドカードとして*.classが使える。
Jarファイルをコマンドで実行するには、-jarオプションを指定する。
java -jar TestApp.jar