年収アップ無料転職カウンセリング実施中! | 転職エージェントはマイナビエージェント

Geekroid-ギークロイド(仮)|ITエンジニアの日常をささいな情報で彩るコラム

ITエンジニアの転職

モジュール

モジュールとは、パッケージを束ねるための単位です。Java 9で追加されました。 モジュールを利用することで、配下のパッケージに対するアクセス権限をより細かに設定できるようになります。具体的には、

・現在のモジュールの中でだけpublic
・特定のモジュールに対してだけpublic
・すべてのモジュールに対してpublic

なパッケージを設定できます。たとえばライブラリをモジュールで束ねることで、そのライブラリの中でだけ利用しているパッケージが、不用意に他のコードからアクセスされることがなくなります(*)。

*)従来のJavaでは、ライブラリ内部でのみ利用するパッケージを不可視にする手段はありませんでした。パッケージプライベートよりも緩い権限が、すぐさま「すべてに対してpublic」だったからです。 標準ライブラリもモジュール

Java 9以降では、標準ライブラリもすべてモジュール化されています。具体的には、コマンドラインから以下のコマンドで確認できます。

> cd C:\pleiades\java\13\bin
> java --list-modules
java.base@13.0.1
java.compiler@13.0.1
java.datatransfer@13.0.1
java.desktop@13.0.1
java.instrument@13.0.1
java.logging@13.0.1
java.management@13.0.1
java.management.rmi@13.0.1
java.naming@13.0.1
java.net.http@13.0.1
…中略…
jdk.rmic@13.0.1
jdk.scripting.nashorn@13.0.1
jdk.scripting.nashorn.shell@13.0.1
jdk.sctp@13.0.1
jdk.security.auth@13.0.1
jdk.security.jgss@13.0.1
jdk.unsupported@13.0.1
jdk.unsupported.desktop@13.0.1
jdk.xml.dom@13.0.1
jdk.zipfs@13.0.1

それぞれのパッケージ(クラス)が属するモジュールは、APIリファレンスからも確認できます。

▲現在のクラスが属するモジュールを確認

モジュールの基本

モジュールを定義するには、ソースフォルダーのトップにモジュール定義ファイル(module-info.java)を配置するだけです。

module-info.java

module mynavi {
}

これでmynaviモジュールを定義したことになります(Eclipseでプロジェクトを作成した場合には、デフォルトでファイルが作成されたことになります)。初期の状態では、{…}の中身は空ですが、最低限モジュールを定義するだけであればこれで十分です。この後、「依存するモジュール」「外部に公開するパッケージ」などを設定する際には、{…}配下にコードを記述していくことになります。

他のモジュールを利用する – requires宣言

モジュールの世界では、デフォルトでは異なるモジュールにはアクセスできません。別のモジュールを利用したい場合には、モジュール定義ファイルにrequires宣言を追加してください。たとえば以下は、java.net.httpモジュールを利用する例です(java.net.httpモジュールには、HttpClientなどHTTP通信に関わるクラスが定義されています)。

module-info.java

module mynavi {
  requires java.net.http;
}

requires宣言なしにjava.net.httpモジュールにアクセスした場合、「The type java.net.http.HttpClient is not accessible」のようなエラーとなります。

note

基本的なコードでrequires宣言を意識しなくてもよかったのは、標準ライブラリのjava.lang、java.ioなど主だったパッケージがjava.baseというモジュールに登録されているからです。java.baseモジュールはrequires宣言なしで無条件にアクセスできるというルールがあります。

推移的な依存関係を宣言する – requires transitive宣言

ただし、モジュールが利用しているモジュールをすべて列挙するのは、中々に厄介です。たとえば、モジュールが利用している先のモジュールで利用しているモジュール(=推移的な依存)をすべて把握するのは大概難しいはずです。

しかし、requires transitive宣言では、そうした推移的な依存を表現できます。たとえば、以下のような例です。

module mod1 {
  requires mod2;
}
-----------------------------------------------------------------------------
module mod2 {
  requires transitive java.net.http;
  requires transitive java.sql;
}

この場合、mod1モジュールはmod2モジュール経由でjava.net.http/java.sqlモジュールに依存していますが、mod1側でこれらのモジュールをrequires宣言する必要はありません。これが推移的な依存関係を宣言する、という意味です(よって、太字を削除した場合、mod1モジュールはjava.net.http/java.sqlモジュールを明示的にrequires宣言しなければなりません)。

配下のパッケージを公開する – exports宣言

モジュール配下のパッケージは、デフォルトでモジュールプライベート(=モジュールの外からはアクセスできない)と見なされます。モジュールの外からパッケージへのアクセスを許可するには、exportsで公開したいパッケージを宣言してください。

たとえば以下はmynaviモジュールからcom.example.mynavi.basicパッケージを公開する例です。

module mynavi {
  exports com.example.mynavi.basic;
}

特定のモジュールに対してのみパッケージを公開したいならば、exports…to宣言を利用します。たとえば、以下はhoge/piyoモジュールに対してのみcom.example.mynavi.basicパッケージを公開する例です。

module mynavi {
  exports com.example.mynavi.basic to hoge, piyo;
}
自動モジュール

モジュールはJava 9で導入された新しいしくみです。よって、暫くは非モジュールなコードとモジュール前提のコードとが混在する状態が続くはずです。このような状態でも、非モジュールをモジュールとして扱えるようにするためのしくみが、自動モジュールです。
具体的には、モジュールパスに配置された.jarファイルで、モジュール定義ファイルを持たないコードは、自動モジュールと見なされます。

note

モジュールパスとは、モジュールの検索先を表すパスのことです。Eclipseであれば、プロジェクトのプロパティから[Javaのビルド・パス]-[ライブラリー]タブから確認できます。

▲プロジェクトのモジュールパス

自動モジュールの名前は、以下のルールで決定します。

・.jarファイルの名前から拡張子とバージョン番号を除去した上で、非英数字をハイフンで置き換えたもの(hoge-piyo-1.0.1.jarならばhoge.piyoがモジュール名)
・META-INF/MANIFEST.MFのAutomatic-Module-Name属性で宣言された名前(Automatic-Module-Name: hoge.piyo)

自動モジュールはあくまで便宜的なモジュールなので、

・配下のすべてのモジュールを公開(exports)
・モジュールパスに登録されたすべてのモジュールをrequires

したのと同じように動作します。

オブジェクト指向構文
class命令
new演算子
フィールドを定義する
static final修飾子
メソッドを定義する
コンストラクターを定義する
package宣言
import命令
import static命令
ネストしたクラスを定義する
モジュール

年収アップ無料転職カウンセリング実施中! | 転職エージェントはマイナビエージェント

Geekroid-ギークロイド(仮)|ITエンジニアの日常をささいな情報で彩るコラム

ITエンジニアの転職