Java 9は、モジュールのコレクションにAPIを組み込みました。したがって、モジュール性が中心的なテーマです。これはトップレベルからのプログラム設計に影響を及ぼしました。プログラムは最初からモジュール式に構築できます。 モジュールと呼ばれるプログラミング要素を具体的に処理するAPIが存在するのは当然のことです。 。 APIは、プログラムでモジュールにアクセスする方法を提供します。これらのAPIは、モジュールに関する特定の情報を取得したり、モジュールを読み取ったり操作したりするのに非常に便利です。この記事では、モジュールAPIクラスといくつかのメソッドについて説明し、それらの全体的な機能を理解するための例を示します。
概要
Java 9は、モジュールをプログラムで処理するための一連のクラスとインターフェースを提供します。これらのAPIは、次の場合に特に役立ちます。
- モジュールの読み取り、読み込み、検索
- モジュール記述子の読み取りと操作
APIのリストは、主にパッケージに含まれています: java.lang およびjava.lang.module 。 java.lang.module パッケージは、モジュール記述子 java.langを処理するためのほとんどのクラスとインターフェイスで構成されています。 パッケージにはクラスが含まれていますモジュール 、 ModuleLayer 、および例外、 LayerInstantiationException 。これら3つのうち、モジュール このクラスのインスタンスは、モジュールの読み取り、ロード、および検索に関連するすべてのメソッドを提供するため、クラスが最も重要です。 java.lang.moduleで最も重要なクラス パッケージはModuleDescriptor 。このクラスは、モジュール記述子を処理するために必要なメソッドを提供します。
モジュールAPI
Java APIドキュメントによると、モジュールクラスは名前付きと名前なしの両方のランタイムモジュールを表します。名前付きモジュールには名前があります モジュールのグラフがJava仮想マシンに定義されてモジュール層が作成されるときに、Java仮想マシンによって構築されます。名前のないモジュールには名前がありません。 ClassLoaderごとに名前のないモジュールがあります 、 getUnnamedModuleを呼び出すことによって取得されます 方法。名前付きモジュールに含まれていないすべてのタイプは、定義しているクラスローダーの名前なしモジュールのメンバーです。
それが属するクラスのモジュールを見つけるのは簡単です。たとえば、クラスのモジュールを調べたい場合は、たとえば ArrayList 、Collection APIから、またはたとえばアプリケーション JavaFXからは、次の方法で行うことができます。
Class<ArrayList> c= ArrayList.class; Module mod=c.getModule(); System.out.println(mod.getName());
または、次のように1つのステートメントで:
System.out.println(Application.class .getModule().getName());
これにより、 java.baseなどのクラスのモジュール名が出力されます。 、 Arraylist の場合 、および javafx.graphics アプリケーションの場合 。モジュールには名前なしまたは名前なしのいずれかを指定できるため、 isNamed()を呼び出すことで確認できます。 方法。このメソッドはtrueを返します モジュールに名前が付けられているか、 false 名前のないモジュールの場合。名前のないモジュールの例を次に示します。
package org.mano.java9.examples; public class Main { public static void main(String[] args) { Class<Main> c= Main.class; Module mod=c.getModule(); System.out.println(mod); System.out.println(mod.getName()); System.out.println(mod.getName()+" is " +(mod.isNamed()? "Named Module":"Unnamed Module")); System.out.println(mod.getDescriptor()); } }
出力:
unnamed module @4c75cab9 null null is Unnamed Module null
また、名前付きモジュールの場合、次のように記述できます。
package org.mano.java9.examples; import java.util.ArrayList; public class Main { public static void main(String[] args) { Class<ArrayList> c= ArrayList.class; Module mod=c.getModule();< System.out.println(mod); System.out.println(mod.getName()); System.out.println(mod.getName()+" is " +(mod.isNamed()? "Named Module":"Unnamed Module")); System.out.println(mod.getDescriptor()); } }
出力:
module java.base java.base java.base is Named Module module { name: [email protected], uses: [java.nio.file.spi.FileTypeDetector, ...}
ModuleLayer 名前付きモジュールのみが含まれます。 getLayerを呼び出すことができます モジュールに含まれるレイヤーに関する情報を取得するメソッド。 nullが返された場合は、モジュールがレイヤーにないか、名前のないモジュールであることを意味します。モジュールで使用可能なパッケージのリストを取得する場合は、 getPackagesを呼び出すことができます。 方法。 getClassLoader メソッドはモジュールクラスローダーを返します。上記の方法を説明する例を次に示します。
package org.app.module1; import javafx.application.Application; import java.util.Set; public class Main { public static void main(String[] args) { Class<Application> c = Application.class; Module mod = c.getModule(); System.out.println("Name :" + mod.getName()); System.out.println(mod.getName() + " is " + (mod.isNamed() ? "Named Module" : "Unnamed Module")); System.out.println("Layer :" + mod.getLayer()); System.out.println("ClassLoader :" + mod.getClassLoader()); System.out.println("List of Packagesn....................."); Set<String> set = mod.getPackages(); int i=1; for (String s : set) { System.out.println(i+++") "+s); } } }
出力:
Name :javafx.graphics javafx.graphics is Named Module Layer :jdk.compiler, java.compiler, jdk.management.jfr, jdk.scripting.nashorn, ... ClassLoader :jdk.internal.loader.ClassLoaders [email protected] .................... List of Packages ..................... 1) com.sun.javafx.stage 2) com.sun.scenario.effect.impl.prism.ps 3) javafx.print ... 107) com.sun.prism.j2d 108) javafx.scene.image
モジュールの説明
Java 9 APIドキュメントによると、「モジュール記述子は名前付きモジュールを記述し、その各コンポーネントを取得するためのメソッドを定義します。」 Java仮想マシンの名前付きモジュールのモジュール記述子は、 Moduleを呼び出すことによって取得されます。 のgetDescriptor 方法。モジュール記述子は、 ModuleDescriptor.Builderを使用して作成することもできます。 クラスまたはモジュール宣言のバイナリ形式を読み取ることによって( module-info.class )読み取りを使用する このクラスで定義されたメソッド。
したがって、通常は ModuleDescriptor instanceは、 module-info.classと呼ばれるモジュール記述子ファイルのバイナリ形式で見つかったモジュール定義を表します。 。モジュール定義の読み取りと操作とは別に、 ModuleDescriptor.Builderを使用できます。 実行時にモジュールを記述するクラス。
モジュール記述子は、通常モジュール、オープンモジュール、自動モジュールなど、3つのタイプのモジュールを記述します。
通常のオープンモジュールは、それらが提供または使用するサービス、依存関係、エクスポートされたパッケージ、およびその他のコンポーネントを明示的に記述します。通常のモジュールと開いているモジュールの主な違いは、通常のモジュールは特定のパッケージを開く可能性があることです。 開いているモジュールのモジュール記述子は、開いているパッケージを宣言しません(開く メソッドは空のセットを返します)が、Java仮想マシンでインスタンス化されると、すべてのパッケージが開いているかのように扱われます。
ただし、自動モジュールは、 java.base の暗黙的な宣言を除いて、エクスポートされた、開いているパッケージ、または依存関係を宣言しません。 モジュール。 自動モジュールがJava仮想マシンでインスタンス化されると、名前のないすべてのモジュールが読み取られ、すべてのパッケージがエクスポートされて開いているかのように扱われます。
getDescriptor モジュールのメソッド クラスはModuleDescriptorのインスタンスを返します クラス。 ModuleDescriptor classには、静的にネストされたクラスが含まれ、そのインスタンスはモジュール宣言ファイルのディレクティブステートメントを表します。ただし、このクラスには用途は含まれていません。 通常、サービスインスタンス文字列で表すことができるステートメント 。他の4つは次のとおりです。
- ModuleDescriptor.Requires
- ModuleDescriptor.Opens
- ModuleDescriptor.Provides
- ModuleDescriptor.Exports
簡単な例
package org.mano.java9.examples; import javax.sql.RowSet; import java.lang.module.ModuleDescriptor; import java.util.List; public class Main { public static void main(String[] args) { System.out.println("Module Name: " + List.class.getModule().getName()); show(List.class.getModule().getDescriptor()); System.out.println("Module Name: " + RowSet.class.getModule().getName()); show(RowSet.class.getModule().getDescriptor()); } public static void show(ModuleDescriptor d) { System.out.println("Module Descriptionn-------------------------"); System.out.println("Requires: " + d.requires()); System.out.println("Exports: " + d.exports()); System.out.println("Uses: " + d.uses()); System.out.println("Provides: " + d.provides()); System.out.println("Packages: " + d.packages()); } }
出力:
Module Name: java.base Module Description ------------------------- Requires: [] Exports: [jdk.internal.org.objectweb.asm.signature to [jdk.scripting.nashorn], ...] Uses: [java.util.spi.LocaleNameProvider, java.nio.file.spi.FileSystemProvider, ...] Provides: [java.nio.file.spi.FileSystemProvider with [jdk.internal.jrtfs.JrtFileSystemProvider]] Packages: [java.nio.file, jdk.internal.org.objectweb.asm .tree.analysis, com.sun.security.ntlm, ...] Module Name: java.sql Module Description ------------------------- Requires: [mandated java.base, transitive java.logging, transitive java.xml] Exports: [java.sql, javax.transaction.xa, javax.sql] Uses: [java.sql.Driver] Provides: [] Packages: [javax.sql, javax.transaction.xa, java.sql]
module-info.classと呼ばれるモジュール記述子バイナリファイル 、を次の方法で直接読み取って、 ModuleDescriptorのインスタンスを作成できます。 クラス:
try { ModuleDescriptor descriptor = ModuleDescriptor .read(new FileInputStream("module-info.class")); } catch (IOException ex) { }
オーバーロードされた静的読み取りには4つのバージョンがあります ModuleDescriptorで定義されたメソッド クラス。これらは、入力ストリームまたはバイトバッファからモジュール記述のバイナリ形式を読み取るために使用されます。これがJava9APIドキュメントからの抜粋です。
- read(InputStream in) :入力ストリームからモジュール記述子としてモジュール宣言のバイナリ形式を読み取ります。
- read(InputStream in、Supplier
> packageFinder) :入力ストリームからモジュール記述子としてモジュール宣言のバイナリ形式を読み取ります。 - read(ByteBuffer bb) :モジュール記述子としてバイトバッファからモジュール宣言のバイナリ形式を読み取ります。
- read(ByteBuffer bb、Supplier
> packageFinder) :モジュール記述子としてバイトバッファからモジュール宣言のバイナリ形式を読み取ります。
packageFinderによるパッケージの設定 モジュールがエクスポート、開く、提供されるサービス、および入力ストリームまたはバイトバッファーで提供される記述子によってエンコードされないメインクラスのパッケージをすべて含みます。
結論
モジュールに関する基本的な情報を読むこととは別に、モジュール クラスは、モジュールのステータス(読み取り、オープン、エクスポートなど)について問い合わせるためのいくつかの重要なメソッドを提供します。 APIは、 addOpensなどのメソッドも提供します 、 addExport 、 addUses 、および addReads プログラムでモジュール記述子にopenおよびexportusesおよびreadステートメントを追加します。一言で言えば、Module APIは、プログラムでモジュールを具体的に処理するための他の多くのメソッドを提供します。ここでは、表面を引っかいて、それが何であるかを最初に理解しました。