Что такое открытый модуль в Java 9 и как его использовать

В чем разница между модулем с открытым ключевым словом до и без него?
Например:

open module foo {
}

module foo {
}

Ответ 1

Чтобы обеспечить отражающий доступ к вашему модулю, Java 9 представила открытое ключевое слово.

Вы можете создать открытый модуль, используя открытое ключевое слово в объявлении модуля.

Открытый модуль предоставляет отражающий доступ ко всем его пакетам к другим модулям.

Например, если вы хотите использовать некоторую фреймворк, которая в значительной степени зависит от отражения, например Spring, Hibernate и т.д., вы можете использовать это ключевое слово, чтобы включить для него отражающий доступ.

Вы можете включить рефлексивный доступ для определенных пакетов вашего модуля, используя инструкцию open в объявлении пакета:

module foo {
    opens com.example.bar;
}

или используя открытое ключевое слово в объявлении модуля:

open module foo {
}

но имейте в виду, что вы не можете их комбинировать:

open module foo {
    opens com.example.bar;
}

с ошибкой времени компиляции.

Надеюсь, что это поможет.

Ответ 2

Немного фона для рассматриваемых директив. Система Система модулей заявляет в разделе Разрыв инкапсуляции

Иногда необходимо нарушать границы доступа определяемый модульной системой и принудительно выполняемый компилятором и виртуальным машины, чтобы один модуль мог получить доступ к некоторым из неэкспонированных типы другого модуля. Это может быть желательным для того, чтобы, например, разрешить тестирование внутренних типов с использованием белого ящика или выставлять неподдерживаемые внутренние API-интерфейсы для кодирования, которые стали зависеть от них. --add-exports можно использовать как время компиляции, так и время выполнения, чтобы сделать это.

Параметр командной строки эквивалентен, например,: -

module java.logging {
    exports java.util.logging;
}

Параметр --add-exports обеспечивает доступ к общедоступным типам указанного пакета.


Хотя после этого

Иногда нужно идти дальше и разрешать доступ ко всем непубличные элементы через метод setAccessible ядра отражение API. Опцию --add-opens можно использовать во время выполнения, чтобы сделайте это.

Эта опция командной строки эквивалентна, например,: -

module jdk.unsupported  {
   opens sun.misc; 
}

Обычный именованный модуль, напротив, определен явно с объявлением модуля как: -

module foo { }

и они известны как явные модули. Явные модули могут использовать директивы для пакетов, как указано выше, например, для пакетов export/open, чтобы обеспечить отражающий доступ к их соответствующим открытым членам и классам.


С другой стороны, модуль open является

который не объявляет никаких открытых пакетов, но результирующий модуль обрабатываются так, как будто все пакеты открыты.

Таким образом, он предоставляет доступ во время выполнения к типам во всех пакетах модулей, как если бы все пакеты экспортировались, что означает, что байт-код или отражение могут использоваться для доступа к каждому классу или членам пакета во всех пакетах. API-интерфейсы отражения с setAccessible или MethodHandles.privateLookupIn допускают глубокое отражение, поэтому вкратце вы можете отразить все члены всех классов во всех пакетах. Который также в значительной степени объясняет, почему компилятор не разрешит открывать директивы для пакета, пока модуль уже открыт.