1. 導入: なぜ「パッケージの公開」が必要なのか
Java 9で導入された「Javaモジュールシステム(Project Jigsaw)」により、Javaのプロジェクト構成は大きく変わりました。これまでのJavaでは、クラスパス上のすべてのクラスは「どこからでもアクセス可能」でしたが、モジュールシステムではデフォルトで隠蔽(カプセル化)されるようになりました。
「exports」は、自分のモジュール内のパッケージを「外部から使えるようにする」ための唯一の入り口です。なぜこれが必要かというと、内部でしか使わない複雑な処理や、外部に公開すべきでない設計を強制的に隠すことで、アプリケーションの堅牢性とセキュリティを向上させるためです。
2. 基礎知識: module-info.java とは
Javaモジュールシステムの中核を担うのが、プロジェクトのルートディレクトリに配置する「module-info.java」というファイルです。
このファイルには、そのモジュールの名前や、依存関係、そして公開するパッケージ(exports)を記述します。
・モジュール: 関連するパッケージをまとめた単位。
・exports: 指定したパッケージ内の public クラスを、他のモジュールから参照可能にするキーワード。
・opens: リフレクション(実行時のクラス解析)を許可するためのキーワード。
3. 実装/解決策: exports の記述方法
モジュールを定義するには、module-info.java に以下のように記述します。
module com.example.service {
// com.example.service.api パッケージを外部に公開する
exports com.example.service.api;
}
これだけで、他のモジュールからは com.example.service.api 内の public クラスにしかアクセスできなくなります。これにより、開発者は「外部に公開する API」と「内部だけで動く実装」を明確に分離できます。
4. サンプルプログラム
以下の構成で、モジュールを定義する例を示します。
// ファイル名: module-info.java
module my.app.core {
// このパッケージを他のモジュールから利用できるように公開します
exports com.myapp.publicapi;
}
// ファイル名: src/com/myapp/publicapi/GreetingService.java
package com.myapp.publicapi;
public class GreetingService {
public void sayHello() {
System.out.println(“こんにちは!モジュールシステムへようこそ。”);
}
}
// ファイル名: src/com/myapp/internal/HiddenLogic.java
package com.myapp.internal;
// このパッケージはexportsしていないため、外部モジュールからは見えません
public class HiddenLogic {
public void execute() {
System.out.println(“これは外部から隠された内部ロジックです。”);
}
}
5. 応用・注意点: 現場でのハマりポイント
現場でよくある失敗は、「パッケージ名が変わったのに module-info.java を更新し忘れる」ことです。
また、Spring FrameworkやHibernateのようなライブラリを使う場合、単に public にするだけでなく、「リフレクション」によるアクセスが必要になることがあります。その場合は、exports ではなく opens を使って公開設定を行う必要があります。
注意点:
・exports はパッケージ単位であり、クラス単位では指定できません。設計段階で公開したいクラスを特定のパッケージにまとめておくことが重要です。
・モジュール化されていないライブラリ(名前のないモジュール)と混在させる場合は、依存関係の解決に少し工夫が必要になるため、まずは小規模なプロジェクトからモジュール化を試すことをおすすめします。
モジュールのカプセル化を理解すると、大規模開発での依存関係が整理され、非常にメンテナンスしやすいコードになります。ぜひ今日から module-info.java を活用してみてください!

コメント