先週はjavax.tools.JavaCompilerインタフェースを使用してJavaのソースをコンパイルする方法について解説しました。しかし,先週説明した範囲ではjavacのメインクラスであるcom.sun.tools.javac.Mainクラスを直接使用するのとほとんど変わりませんでした。

そこで,今週からJavaCompilerインタフェースの特有の機能について紹介していきます。

基本的な使用法

JavaCompilerインタフェースの機能を活用するには,先週紹介したrunメソッドを使わずにコンパイルを行います。

その代わり,仮想的なファイルマネージャであるjavax.tools.StandardJavaFileManagerインタフェースと,コンパイルを行うタスクを表すJavaCompiler.CompilationTaskインタフェースを使用します。

サンプルのソース(こちらからダウンロードできます)
CompilerAPISample4.java

まず,コンパイルするJavaのソースファイルを準備する部分を示します。

        // コンパイラの取得
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
 
        // 仮想ファイルマネージャの取得
        StandardJavaFileManager fileManager 
            = compiler.getStandardFileManager(null, null, null);
 
        // コンパイルするファイルの準備
        Iterable<? extends JavaFileObject> fileobjs =
            fileManager.getJavaFileObjects("Hello.java");

JavaCompilerオブジェクトは先週紹介したように,javax.tools.ToolProviderクラスのgetSystemJavaCompilerメソッドを使用して取得します。

StandardJavaFileManagerインタフェースは,抽象的なファイルを表すjavax.tools.JavaFileObjectインタフェースを操作するためのインタフェースです。このJavaFileObjectインタフェースはFileクラスに対応するインタフェースです。

StandardJavaFileManagerインタフェースのオブジェクトは,青字で示したようにJavaCompilerインタフェースのgetStandardFileManagerメソッドを使用することで取得できます。

StandardJavaFileManagerオブジェクトを取得するためのgetStandardFileManagerメソッドの第1引数はコンパイルエラーに関するDiagnosticListenerオブジェクトを指定します。このDiagnosticListenerインタフェースについては後述します。

第2引数はロケール(java.util.Localeクラス),第3引数は文字セット(java.nio.charset.Charsetクラス)を指定します。

いずれの引数もnullを指定することで,デフォルトの値が適用されます。つまり,ロケールはデフォルトロケール,文字セットはプラットフォームのデフォルトの文字セットが使用されます。ここでは,すべてnullとしています。

次に,コンパイルするJavaのソースファイルに対するJavaFileObjectオブジェクトを取得します(赤字部分)。

CompilationTaskインタフェースで扱うソースファイルはJavaFileObjectオブジェクトで表します。そのため,実際のソースファイルに対応するJavaFileObjectオブジェクトを取得する必要があるのです。

JavaFileObjectオブジェクトを取得するにはStandardJavaFileManagerインタフェースのgetJavaFileObjectsメソッドを使用します。getJavaFileObjectsメソッドには引数が文字列のものとFileオブジェクトのものがあります。いずれも,可変引数になっているので,コンパイルするファイルを列挙します。

これ以外に,コレクションを引数に取れるgetJavaFileObjectsFromStringsメソッドもしくはgetJavaFileObjectsFromFilesメソッドも提供されています。

これらのメソッドの戻り値の型はいずれもIterable<? extends JavaFileObject>です。java.lang.IterableインタフェースはJ2SE 5.0で導入された拡張for文で使用するためのインタフェースです。

Listオブジェクトなどを拡張for文で扱えるのは,java.util.CollectionインタフェースがIterableインタフェースの派生インタフェースだからなのです。