4 モジュール・インポート宣言
モジュールによってエクスポートされたすべてのパッケージを1つの文でインポートできます。
ノート:
これはプレビュー機能です。プレビュー機能は、設計、仕様および実装が完了したが、永続的でない機能です。プレビュー機能は、将来のJava SEリリースで、異なる形式で存在することもあれば、まったく存在しないこともあります。プレビュー機能が含まれているコードをコンパイルして実行するには、追加のコマンド行オプションを指定する必要があります。『Preview Language and VM Features』を参照してください。モジュール・インポート宣言の詳細は、JEP 476を参照してください4つのクラスをインポートする次の例について考えてみます:
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class FruitMap {
public static void main(String[] args) {
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()));
m.forEach((k, v) ->
System.out.println(k + " " + v));
}
}
この例にある4つの単一型インポート宣言をオンデマンド型インポート宣言に置き換えることができます。しかし、そのうちの3つはまだ必要です
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
モジュールjava.baseはパッケージjava.util、java.util.functionおよびjava.util.streamをエクスポートするため、この3つの宣言を1つのモジュール・インポート宣言に置き換えることができます:
import module java.base;
モジュール・インポート宣言の形式は次のとおりです:
import module M;
次のものに含まれる最上位のpublicクラスおよびインタフェースのすべてをオンデマンドでインポートします:
-
モジュール
M
によって現在のモジュールにエクスポートされたパッケージ。 -
モジュール
M
の読取りのために現在のモジュールによって読み取られるモジュールによってエクスポートされたパッケージ。これにより、プログラムは他のモジュールのクラスおよびインタフェースを参照するモジュールのAPIを使用できるため、他のモジュールをすべてインポートする必要がなくなります。たとえば、モジュール・インポート宣言
import module java.sql
には、import java.sql.*
とjava.sqlモジュール(パッケージjava.loggingおよびjava.xmlを含む)の間接エクスポートのためのオンデマンド・インポートを合せて使用する場合と同じ効果があります。
あいまいなインポート
モジュール・インポート宣言を使用して、異なるパッケージから同じ単純名を持つクラスをインポートすることは可能です。ただし、これはコンパイル時のエラーにつながる可能性があります。次の例では、java.awt.Listとjava.util.Listの両方を使用しています:
import java.awt.Frame;
import java.awt.Label;
import java.awt.List;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Arrays;
public class FruitApp {
AWTExample(java.util.List<String> fruits) {
Frame f = new Frame();
Label l = new Label("Fruits");
List lst = new List();
fruits.forEach(i -> lst.add(i));
l.setBounds(20, 40, 80, 30);
lst.setBounds(20, 70, 80, 80);
f.add(l);
f.add(lst);
f.setSize(200,200);
f.setTitle("Fruit");
f.setLayout(null);
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
}
public static void main(String args[]) {
String[] fruits = new String[] { "apple", "berry", "citrus" };
FruitApp f = new FruitApp(Arrays.asList(fruits));
}
}
単一型インポート宣言を次のモジュール・インポート宣言に置き換えるとします:
import module java.desktop;
import module java.base;
次のようなコンパイル時のエラーが発生します:
error: reference to Label is ambiguous
Label l = new Label("Fruits");
^
both interface java.lang.classfile.Label in java.lang.classfile and class
java.awt.Label in java.awt match
...
error: reference to List is ambiguous
List lst = new List();
^
both interface java.util.List in java.util and class java.awt.List in java.awt
match
単純名Labelはあいまいです。java.lang.classfileとjava.awtに含まれており、これらはモジュールjava.baseおよびjava.desktopによってそれぞれエクスポートされます。この問題は、単純名Listにも同様に当てはまります。
これらのあいまいさを解決するには、単一型インポート宣言を使用して、コードで使用される単純名の正規名を指定します:
import module java.desktop;
import module java.base;
import java.awt.Label;
import java.awt.List;
暗黙的に宣言されたクラスおよびjava.baseモジュール
暗黙的に宣言されたすべてのクラス(「暗黙的に宣言されたクラス」を参照)は、java.baseモジュールによってエクスポートされたすべてのパッケージに含まれる最上位のpublicクラスおよびインタフェースのすべてをオンデマンドで自動的にインポートします。これは、オンデマンド型インポート宣言import java.lang.*
がすべての通常のクラスの先頭に出現するのではなく、モジュール・インポート宣言import module java.base
が暗黙的に宣言されたすべてのクラスの先頭に出現する場合と同じ動作です。たとえば、暗黙的に宣言されたクラスを使用して、FruitMap
の例を次のように簡略化できます:
void main() {
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()));
m.forEach((k, v) ->
System.out.println(k + " " + v));
}