JEP 511 Module Import Declarations

blog1.mammb.com


はじめに

JDK 25 からインポート宣言にモジュール名を指定できるようになります。

import module java.base;

例えば以下のようなストリーム処理を行う単純なコードは、

String[] fruits = new String[] { "apple", "berry", "citrus" };
Map<String, String> m = Stream.of(fruits)
    .collect(Collectors.toMap(
        s -> s.toUpperCase().substring(0,1), Function.identity()));

以下の単一型インポート宣言(single-type-import)が必要で、ストリーム処理のコードと同じ行数が必要となります。

import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

オンデマンド型インポート宣言(type-import-on-demand)(いわゆるスターインポート)を使ったとしても、3行のインポート宣言が必要です。

import java.util.*;
import java.util.function.*;
import java.util.stream.*;

モジュールインポートを使えば、以下の宣言で完了します。

import module java.base;

モジュールインポートは、JDK 23でプレビュー公開(JEP 476)され、JDK 24で改良されたセカンドプレビュー公開(JEP 494)となったものがJDK 25でそのまま最終版として提案されました。


モジュールインポート

インポート宣言の文法に ModuleImportDeclaration が追加となります。

ImportDeclaration:
  SingleTypeImportDeclaration
  TypeImportOnDemandDeclaration
  SingleStaticImportDeclaration
  StaticImportOnDemandDeclaration
  ModuleImportDeclaration

ModuleImportDeclaration:
  import module ModuleName;

以下のようなインポート宣言は、

import javax.xml.*;
import javax.xml.parsers.*;
import javax.xml.stream.*;

以下のように簡略化して書くことができます。

import module java.xml;

モジュールインポートの特徴は以下になります。

  • モジュール全体を一度に(オンデマンド)インポートできる
  • インポート宣言を行うコード自体は、モジュール定義されたものでなくとも良い
  • モジュール宣言で exports されたパッケージに加え、requires transitive で遷移的に依存するモジュールも合わせてインポート処理される
  • 名前のないモジュールをモジュールインポートすることはできない
  • モジュールインポートは、他のインポート宣言より優先度が低い(他のインポート宣言でシャドーイングできる)

特に説明が必要なのは、モジュールインポートの優先度(特定性)ぐらいでしょう。 以下のようにモジュールインポートを行った場合、Date クラスの使用はエラーになります。

import module java.base;
import module java.sql;

Date d = ...  // Error - java.util,Date vs java.sql,Date

java.util,Datejava.sql,Date かを特定できないためです。

このような曖昧さを解消するには、単一型インポート宣言を追加してモジュールインポートをシャドーイングします。

import module java.base;
import module java.sql;
import java.sql.Date;

Date d = ...  // Ok!  Date は java.sql.Date として解決される

つまり、インポート宣言の特定性は以下の順に高くなり、上のものは下のものでシャドーイングできます。

  • モジュールインポート
  • オンデマンド型インポート(type-import-on-demand)
  • 単一型インポート(single-type-import)


まとめ

JDK 25 からモジュール名を指定した一括インポートが可能になりました。

大規模なプロジェクトでは、単一型インポート(single-type-import)を使用しておくのがベータです(例えば OpenRewrite などで大規模なマイグレーションを行う際に後悔することになる)。

が、教育目的やプロトタイプ開発、小規模開発時には便利に使えるでしょう。

JEP 512: Compact Source Files and Instance Main Methodsでは暗黙的に import module java.base; されたものとして扱われます。また、これは JShell についても同様です。