分割コンパイル
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