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

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

open module foo {
}

module foo {
}

3 ответа

Решение

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

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

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

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

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

module foo {
    opens com.example.bar;
}

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

open module foo {
}

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

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

результаты с ошибкой во время компиляции.

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

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

Иногда необходимо нарушить границы контроля доступа, определенные модульной системой и применяемые компилятором и виртуальной машиной, чтобы позволить одному модулю получить доступ к некоторым из неэкспортированных типов другого модуля. Это может быть желательно для того, чтобы, например, включить тестирование внутренних типов в "белой коробке" или предоставить неподдерживаемые внутренние 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 учитывайте глубокие размышления, так что вкратце вы можете размышлять над всеми членами всех классов во всех пакетах. Что также в значительной степени объясняет причину, по которой компилятор не допускает обе директивы open для пакета, пока модуль уже открыт.

Предположим, что 'foo' имеет два пакета: com.example и com.example.bar.

      module foo {
    opens com.example;
}

Вышеупомянутое объявление модуля разрешает рефлексивный доступ для типов внутри пакета com.example во время выполнения за пределами.

Но com.example не будет виден во время компиляции снаружи.

      open module foo {
}

Это означает, что он неявно открывает все пакеты в модуле для среды выполнения для отражающего доступа.

Вышеупомянутый модуль declaratoin будет соответствовать следующему:

      module foo {
    opens com.example;
    opens com.example.bar;
}
Другие вопросы по тегам