一致する検索結果がありませんでした。
お探しのものを見つけるために、以下の項目を試してみてください。
内容と使用方法
Paul Deitel
Paul Deitel
この記事では、Javaの誕生以来、その最も重要な新しいソフトウェア・エンジニアリング・テクノロジーであるJava 9 Platform Module System(JPMS)を紹介します。Project Jigsawの成果であるモジュール性により、あらゆるレベルの開発者が、ソフトウェア・システム、特に大規模システムの構築、保守、変更を行う際に、より生産的な作業ができるようになります。
モジュール性により、パッケージより上位レベルの集合体が追加されます。新しい言語の主要な要素は module で、一意に名付けられた再利用可能な関連パッケージのグループと、リソース (イメージや XML ファイルなど)、および、以下を指定する module descriptor です。
Java SEプラットフォームは1995年に誕生しました。現在、およそ1,000万人の開発者が、Internet of Things (IoT)やその他の組込みデバイスなど、リソース制約のあるデバイス用の小規模なアプリケーションから、大規模かつビジネスに必要不可欠であるミッションクリティカルなシステムに至るまで、すべてを構築しています。世の中には膨大な種類のレガシー・コードがありますが、これまでJavaプラットフォームは主にモノリシックなフリー・サイズ型のソリューションでした。長年にわたり、Javaのモジュール化に向けた様々な取り組みが行われてきましたが、どれも広く使われておらず、Javaプラットフォームのモジュール化に使えるようなものはありませんでした。
Java SEプラットフォームのモジュール化は難しく、その取り組みには長い年月を要していました。JSR 277: Java Module Systemは当初、2005年にJava 7用に提案されました。このJSRは、後でJSR 376: Java Platform Module Systemによって置き換えられ、Java 8を対象にしました。Java SEプラットフォームは、Java 9でモジュール化されました。しかしそれは、Java 9が2017年9月まで延期された以降の話です。
各モジュールは、その依存関係を明示的に指定する必要があります。
JSR 376によると、Java SEプラットフォームのモジュール化の主な目標は以下の通りです。
JEP 200: モジュラーJDK
JEP 201: モジュラー・ソース・コード
JEP 220: モジュラ・ランタイム・イメージ
JEP 260: ほぼ全ての内部APIのカプセル化
JEP 261: モジュール・システム
JEP 275: モジュラーJAVAアプリケーション・パッケージング
JEP 282: JLINK: THE JAVA LINKER
JSR 376: JAVAプラットフォーム・モジュール・システム
JSR 379: JAVA SE 9
表1Javaモジュール性JEPとJSR
Java9の重要な点は、JDKをモジュールに分割し、さまざまな構成に対応できるようにしたことです。(「JEP 200: The Modular JDK」を参照。」すべての JavaモジュラリティーJEPおよびJSRを 表1に示します。)JDKのbinフォルダからjavaコマンドで、--list-modules
オプションをつけて、以下のように使用します。
java --list-modules
には、JDKのモジュール群がリストアップされており、Java言語SE仕様を実装した標準モジュール(java
で始まる名前)、JavaFXモジュール(javafx
で始まる名前)、JDK固有のモジュール(jdk
で始まる名前)、Oracle固有のモジュール(oracle
で始まる名前)などが含まれています。各モジュール名のあとのバージョン文字列- @9
は、モジュールが Java 9に属していることを示します。
前述の通り、モジュールはモジュール記述子(モジュールの依存関係、モジュールが他のモジュールに提供するパッケージなどを指定するメタデータ)を提供する必要がありますモジュール記述子は、module-info.java
というファイルに定義されているモジュール宣言をコンパイルしたものです。各モジュール宣言は、次に示すように、キーワードmodule
で始まり、その後に一意のモジュール名と中カッコで囲まれたモジュール本体が続きます。
モジュールシステムの主な目的は、強力なカプセル化にあります。
module modulename {
}
モジュール宣言の本文は空にすることも、requires
、exports
、provides...with
、uses
およびopens
など、様々なモジュール・ディレクティブを含めることもできます(それぞれで説明します)。後で確認するように、モジュール宣言をコンパイルすると、モジュール記述子が作成されます。モジュール記述子は、モジュールのルート・フォルダ内のmodule-info.class
という名前のファイルに格納されます。ここでは、各モジュール・ディレクティブについて簡単に説明します。その後、実際のモジュール宣言を示します。
キーワードexports
、module
、open
、opens
、provides
、requires
、uses
、with
、および後で紹介するto
およびtransitive
は制限付きキーワードです。これらはモジュール宣言でのみキーワードであり、コード内のどこでも識別子として使用できます。
requires.requires
モジュール・ディレクティブは、このモジュールが別のモジュールに依存することを指定します。この関係はモジュール依存性と呼ばれます。各モジュールは、その依存関係を明示的に指定する必要があります。モジュールAがモジュールBをrequires
した場合、モジュールAはモジュールBを読み取り、モジュールBはモジュールAによって読み取られます。別のモジュールへの依存性を指定するには、次のようにrequires
を使用します。
requires modulename;
また、コンパイル時には必要だが、実行時には任意であることを示すrequires static
指示文もあります。これは optional dependency として知られており、この紹介では説明しません。
requires transitive(暗黙の可読性).他のモジュールへの依存関係を指定し、自分のモジュールを読んでいる他のモジュールもその依存関係を読むようにするには、implied readability として知られている requires transitive
を以下のように使用します。
requires transitive modulename;
java.desktop
モジュール宣言から、次のディレクティブを考えます。
requires transitive java.xml
;
この場合、java.desktop
を読み取るいかなるモジュールも、暗黙的にjava.xml
を読み取ります。たとえば、java.desktop
モジュールのメソッドがjava.xml
モジュールからタイプを返す場合、java.desktop
を読み取るモジュール内のコードはjava.xml
に依存します。java.desktop
のモジュール宣言にrequires transitive
ディレクティブがない場合、java.xml
を明示的に読み取らないかぎり、このような依存モジュールは構成されません。
JSR 379 によると、Java SEの標準モジュールは、ここで説明したようなすべてのケースで暗黙の可読性を付与する必要があります。また、Java SE標準モジュールは非標準モジュールに依存することがありますが、暗黙の可読性を与えてはいけません。これにより、Java SE標準モジュールにのみ依存するコードは、Java SE実装間で移植可能であることが保証されます。
exports and exports…to.exports
モジュール指示文は、他のすべてのモジュールのコードから public
型 (とその入れ子の public
と protected
型) にアクセスできるようにするモジュールのパッケージの一つを指定します。exports...to
ディレクティブは、エクスポートされたパッケージにアクセスできるモジュールのコードをカンマ区切りで指定することができ、これは qualified エクスポートとして知られています。
uses.uses
モジュール・ディレクティブは、このモジュールによって使用されるサービスを指定し、モジュールをサービス・コンシューマーにします。serviceは、インタフェースを実装したクラス、またはuses
ディレクティブで指定されたabstract
クラスを拡張するクラスのオブジェクトです。
provides…with.provides…with
モジュール・ディレクティブは、モジュールがサービス実装を提供することを指定し、モジュールをサービス・プロバイダーにします。provides
の部分は、モジュールの uses
ディレクティブにリストされているインタフェースまたは abstract
クラスを指定し、 with
の部分は、implements
インタフェースまたは extends
abstract
クラスのサービス・プロバイダ・クラスの名前を指定します。
open, opens, and opens…to.Java 9以前では、リフレクションを使用して、パッケージ内のすべてのタイプと、この機能を許可するかどうかに関係なく、タイプのすべてのメンバー( private
メンバーも含む)について学習できました。したがって、真にカプセル化されているとは言えませんでした。
ジュールシステムの主な目的は、強力なカプセル化にあります。デフォルトでは、モジュールのタイプが、パブリックタイプかつそのパッケージをエクスポートしない限り、他のモジュールからアクセスできません。公開するパッケージのみを公開します。Java 9において、これはリフレクションにも適用されます。
パッケージへの実行時のみアクセスを許可します。フォームのオープン・モジュール・ディレクティブ
opens package
特定のパッケージのpublic
タイプ(およびそのネストされたpublic
およびprotected
タイプ)が実行時にのみ他のモジュールのコードにアクセスできることを示します。また、指定したパッケージ内のすべてのタイプ(およびすべてのタイプのメンバー)には、リフレクションを介してアクセスできます。
特定のモジュールによるパッケージへの実行時のみアクセスを許可します。フォームのopens...to
モジュール・ディレクティブ
opens package to comma-separated-list-of-modules
特定のパッケージのpublic
タイプ(およびそのネストされたpublic
およびprotected
タイプ)が実行時にのみリストされているモジュールのコードにアクセスできることを示します。指定したパッケージのすべてのタイプ(およびすべてのタイプのメンバー)は、指定されたモジュールのコードに対するリフレクションを介してアクセスできます。
モジュール内のすべてのパッケージへのアクセスを実行時のみ許可します。もし、与えられたモジュール内のすべてのパッケージが、実行時に、他のすべてのモジュールにリフレクションを介してアクセス可能であるべきなら、次のように、モジュール全体をopen
することができます。
open module modulename {
// module directives
}
デフォルトでは、パッケージへの実行時リフレクト・アクセス権を持つモジュールは、パッケージのpublic
タイプ(およびそのネストされたpublic
およびprotected
タイプ)を表示できます。しかし、他のモジュールのコードは、以前のJavaバージョンと同様に、setAccessible
によって、private
メンバーを含む、公開されたパッケージ内のすべてのタイプとそれらのタイプ内のすべてのメンバーにアクセスすることが可能です。
setAccessible
およびリフレクションの詳細は、オラクルのドキュメントを参照してください。
Paul Deitel氏は、Deitel & AssociatesのCEO兼最高技術責任者で、MITを卒業し、35年にわたるコンピュータ業界での経験を有しています。Javaチャンピオンで、22年以上Javaでプログラミングを行っています。Deitel氏と共著者のHarvey M博士Deitel氏は、世界で最も売れているプログラミング言語に関する執筆者です。同氏は、は、Java、Android、iOS、C#、C++、C、インターネット・プログラミング・コースを、産業界、政府、学術界の顧客に国際的に提供してきました。
注:この記事はJava Magazine 2017年9月/10月号から抜粋したものです。