Java 入門

ホーム > コンパイルとプログラムの実行 > 分割コンパイルと CLASSPATH

分割コンパイルと CLASSPATH

通常アプリケーションは複数のソースコードから作成されます。

Java でも、やはりというか、当然ながらというか、複数のファイルからプログラムを構築することが可能です。

ここでは簡単なサンプルを用いて、実際にプログラムを作成しながら、複数のファイルを扱う方法をみていきましょう。

複数のファイルを参照するソースコードのコンパイル

ここではまず、次のような Person クラスを定義します。これは 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 として、Person.java と同じディレクトリに保存してください。

public class TestApp {
	public static void main(String[] args) {
		Person p = new Person(10, "Mike");
		p.printName();
		p.printAge();
	}
	
}

ポイントは TestApp.java にて、Person クラスを利用していることです。

TestApp.java をコンパイルしてみましょう。

> javac TestApp.java

すると TestApp.class の他、自動的に Person.java もコンパイルされ Person.class が作成されました。

このように javac では必要に応じて、クラスを探してそれを利用します。

クラスを探すのは、環境変数 CLASSPATH で指定された場所を探します。指定が無い場合は「.」(現在のディレクトリ) です。

例えば、ここで Person.java をサブディレクトリ dir1 に配置したとします。この場合、CLASSPATH を指定しない場合は Person.java を見つけることができず、 次のようなエラーとなり TestApp.java のコンパイルに失敗します。

> javac TestApp.java
TestApp.java:4: error: cannot find symbol
                Person p = new Person(10, "Mike");
                ^
  symbol:   class Person
  location: class TestApp
TestApp.java:4: error: cannot find symbol
                Person p = new Person(10, "Mike");
                               ^
  symbol:   class Person
  location: class TestApp
2 errors

シンボル Person なんて知らない、というわけです。

これを解消するには javac が Person を見つけられるように、次のように環境変数を設定します。

> SET CLASSPATH=.;.\dir1

「;」セミコロンで区切って、パスを複数指定できます。ここでは現在のディレクトリを表すドット (.) と、 現在のディレクトリのサブディレクトリ dir1 (.\dir1) の二つを指定しています。

CLASSPATH を指定すればコンパイルは成功します。

javac のコンパイルオプションとして -verbose を指定すると、確かに次のようにソースファイル及びクラスファイルの検索パスとして、 . と .\dir1 が含まれていることが確認できます。

> javac -verbose TestApp.java
[parsing started RegularFileObject[TestApp.java]]
[parsing completed 22ms]
[search path for source files: .,.\dir1]
[search path for class files: C:\Program Files\Java\
ram Files\Java\jdk1.7.0_51\jre\lib\charsets.jar,C:\P
\jre\lib\ext\jaccess.jar,C:\Program Files\Java\jdk1.
1\jre\lib\ext\zipfs.jar,.,.\dir1]
[loading ZipFileIndexFileObject[C:\Program Files\Jav
[loading ZipFileIndexFileObject[C:\Program Files\Jav
[checking TestApp]
[loading ZipFileIndexFileObject[C:\Program Files\Jav
[loading RegularFileObject[.\dir1\Person.class]]
[wrote RegularFileObject[TestApp.class]]
[total 513ms]

さらに次のように Person から派生した Employee クラスを定義して、TestApp.java からそれを使う場合も全く同様にコンパイルできます。

Employee.java は次の通り。

public class Employee extends Person {
	
	private String company;
	
	public Employee(
		int age, String name, String company){
		super(age, name);
		this.company = company;		
	}
	
	public void printCompany(){
		System.out.println(company);
	}
	
}

TestApp.java は次の通り。

public class TestApp {

	public static void main(String[] args) {
		Employee p = new Employee(
			25, "Mike", "Google");
		p.printName();
		p.printAge();
		p.printCompany();
	}
	
}

この場合も TestApp.java だけを javac に渡しても、直接 TestApp.java から参照している Employee 以外に Person.java もコンパイルされます。

プログラムの実行は java にクラス名を渡して、次のようになります。

> java TestApp
Mike
25
Google
ホーム > コンパイルとプログラムの実行 > 分割コンパイルと CLASSPATH