はじめに
モジュール機能はJava 9にとって最も大きな変更といえます。コードだけを見ると、ほんのわずかな違いに思えますが、その意味を知れば知るほど、この変更によるJava自身の変化の大きさに気づくのではないかと思います。
また、このモジュール機能は、機能の追加というよりもポリシー自体の変更と表現したほうが適切でしょう。それは、既存の環境だけではなく新しい環境に対して必要なことであり、Javaの用途がさらに広がったことを意味するのではないかと思います。
対象読者
- Java関連に携わる開発者
- これからJavaを学ぼうと思っている方
モジュール機能「Project Jigsaw」とは(1)
Javaでこれまでモジュールといえばパッケージの概念と同じでした。しかしJava 9ではパッケージとは別に、モジュールという新たな概念が追加されています。
Javaのクラスやメソッド、そしてフィールドなどには、公開範囲を定義するためのprivateやpublicといった定義がありました。しかし、パッケージについては「どのパッケージを参照すればいいか」や「どのパッケージは利用してはいけないか」の定義はありませんでした。
これらのパッケージの使用可否は、実行時にクラスパスに追加されているかどうかで判定していました。しかしJava 9のモジュール機能では、プログラミング時にパッケージ単位で参照を制限することができます。
例えば、ライブラリ開発時にもモジュールを使用することによって、ライブラリ内で使っているpublicなクラスをライブラリ利用者に対して公開しないといったことが可能になります。これはモジュール機能のひとつに過ぎませんが、開発者にとっては最もわかりやすい機能といえるでしょう。
モジュール機能がカバーする範囲は広いですが、作成するために必要な手順はそれほど多くありません。実際にモジュール機能で何ができるかは、説明のみだと少々わかりにくいため、実際に作りながら確認していきます。
モジュール定義ファイルの概要
早速、モジュールの定義方法を紹介します。モジュールを定義する方法は非常に簡単で、ソースフォルダ(より正しくは/classesフォルダの配下)の直下に「module-info.java」という名前のモジュール定義ファイルを用意します。モジュール定義ファイルには、以下の内容を宣言します。
- どのモジュールを使うかの宣言
- どのパッケージを他のモジュールに対して公開するかの宣言
したがって、基本的な考え方はあまり難しくありません。
モジュール定義ファイル内で利用するモジュールを宣言する場合は、リスト1の通りにrequiresを使って宣言します。これは「com.coltware.mainモジュールでjava.sql、com.colware.modを使います」という意味を表します。
module com.coltware.main { requires java.sql; requires com.coltware.mod; }
モジュール名がパッケージ名と一致しているため、利用するパッケージを宣言しているように見えます。しかし、パッケージ名とモジュール名は必ずしも同じにする必要はなく、モジュール名は自由につけることができます。
次回説明予定ですが、Java 9のモジュールに対応していないライブラリを使うケースもあります。その場合は、ファイル名の一部が自動的にモジュール名になります。
ここではパッケージ名ではなくモジュール名だという点に注意してください。ただし、モジュール名はパッケージ名と同じであるほうが、対応関係を類推しやすくもなります。JDK内部でも、パッケージ名を元にしたモジュール名が定義されているため、これに沿うようにしたほうが無難でしょう。
Note
モジュール定義ファイルに似た仕組みとしてパッケージごとに配置できるpackage-info.javaがありますが、module-info.javaファイルはソースフォルダ配下に1つしか置けません。
module-info.javaの作り方
実際にコードを記述する際には、IDEを使っているケースが多いと思います。使っているIDEによっても、このmodule-info.javaの作り方が異なります。
例えば、Eclipseの場合にはソースフォルダ(デフォルトパッケージ)直下にて、図1のように通常のファイル作成で行います。
通常のファイル作成のダイアログが表示されたところで、図2のようにmodule-info.javaというファイル名でファイルを作成します。
ファイル作成で行っているため、ファイルの中身は空の状態で作成されます。クラス作成などのようにテンプレートは用意されていません。
ただし、Eclipse内ではこのmodule-info.javaというファイルがあればモジュール機能が有効になります。
例えば、利用を宣言していないパッケージをimportしようとすると図3のエラーが表示されます。このエラー内容の「Add 'requires [package名] to module-info.java file」をクリックすると、そのままmodule-info.javaファイル内にコードが追加されます。しかし、module-info.javaファイルがないとこのエラーは表示されず、モジュールの機能が有効になっていないことがわかります。
また、Eclipseの場合にはmodule-info.javaというファイルがどこにあってもエラーにはなりません。ただし、実際にパッケージングする際には正常に動作しなくなるため注意が必要です。
module-info.javaファイル自体でSyntaxエラーになる場合には、利用しているJREのバージョンが9であることを確認してください。
また、筆者はIntelliJ IDEAも使います。こちらのほうがJava 9への対応度が高い印象を受けます。例えば、図4のようにコンテキストメニューにmodule-info.javaファイルを作成するメニューが表示されます。
ただし、利用するJDKのバージョンがJava 9になっていない場合や、ソースフォルダの直下でないところでファイルの作成を試みても、このmodule-info.javaの作成のメニューは表示されません。
このように、利用するIDEによっては癖もあるため、IDEを使って試す場合は気をつけてください。