В чем разница между требованиями и требованиями транзитивных операторов в Java 9?

в чем разница между требует и требует транзитивное операторы модуля в объявлении модуля?

Например:

module foo {
    requires java.base;
    requires transitive java.compiler;
}

6 ответов


Readability recap

если модуль бар requires модуль пить, затем модуль системы...

  • обеспечивает наличие пить (под названием надежная конфигурация)
  • позволяет бар читать пить (под названием читабельности)
  • позволяет код бар для доступа к публичным классам в экспортированные пакеты в пить (под названием доступность)

точно так же произойдет, если бар requires transitive drink -пить должен присутствовать, может быть прочитан и доступен. На самом деле, для бар и пить the transitive ключевое слово ничего не меняет.

подразумевает читабельность

модули в зависимости от бар несколько те, на которые влияет transitive: любой модуль, который читает бар также можно прочитать пить. Другими словами читаемость пить is подразумевается (вот почему это называется подразумевает читабельность). Следствием является то, что клиент доступ пить - х типов.

если bar requires transitive drink и customer requires bar, потом клиент можете узнать пить хотя это явно не зависит от него.

варианты использования

но почему? Представьте, что у вас есть модуль, открытый API которого принимает или возвращает тип другого модуля. Скажем бар модуль публично возвращает экземпляры Drink интерфейс от пить модуль:

// in module _bar_
public class Bar {

    // `Drink` comes from the module _drink_,
    // which _bar_ requires
    public Drink buyDrink() { /* ... */ }

}

в этом примере бар использует обычный requires на пить. Теперь скажи:"!--17-->клиент зависит от бар, поэтому весь его код может вызвать Bar::buyDrink. Но что происходит, когда это происходит?

модульная система жалуется на то, что клиент не читал пить и, следовательно, не может получить доступ к Drink. Чтобы исправить это, клиент также должен зависеть от пить. Что муторно! Насколько бесполезен бар, который вы не можете использовать сразу?

customer requires bar requires drink - but how does customer read drink?

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

если bar requires transitive drink, клиент можно начать покупать напитки без необходимости require drink - require bar хватает. Как надо.


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

если один модуль экспортирует пакет, содержащий тип, подпись которого ссылается на пакет во втором модуле, а затем на объявление первый модуль должен включать requires transitive зависимость от второй. Это будет гарантировать, что другие модули, которые зависят от первый модуль автоматически сможет читать второй модуль и, следовательно, доступ ко всем типам в экспортированных пакетах этого модуля.


Итак, скажем, для вашего случая использования: -

module foo {
    requires java.base;
    requires transitive java.compiler;
}

~> любой модуль, который зависит от foo модуль автоматически прочитает java.compiler модуль

~> С другой стороны, чтобы получить доступ к модулю java.base, они должны указать requires снова пункта.

module bar {
    requires foo; // java.compiler is available to read
    requires java.base; // still required
}

requires описывает процесс разрешения того, как модули зависят друг от друга.

цитируя строки

директива "requires" (независимо от "transitive") выражает, что один модуль зависит от другого модуля. действие "транзитивный" модификатор должен вызывать дополнительные модули, которые также зависят от другой модуль. Модуль If M 'требует транзитивного N', то не только зависит ли M от N, но любой модуль, который зависит от M, также зависит от N. Это позволяет M быть refactored так, что некоторое или все из своего содержания может быть перемещен в новый модуль N без нарушения модулей, которые имеют "требуется директива M".

короче :

requires - M модуль зависит от некоторого другого модуля N.

requires transitive - дополнительные модули неявно зависят от другого модуля. Например:, если модуль M зависит от N, а другой модуль P зависит от M. тогда он также неявно зависит от N.


Николай объяснил подробно. Я просто даю конкретный пример из кода JDK здесь. Рассмотрим состав JDK.описание.модуль Насхорн. Модуль-информация этого модуля выглядит следующим образом:

http://hg.openjdk.java.net/jdk9/dev/nashorn/file/17cc754c8936/src/jdk.scripting.nashorn/share/classes/module-info.java

Он имеет эту строку:

requires transitive java.scripting;

это так пакета JDK.описание.нэшорн!--6--> собственный API модуля в пакета JDK.описание.прикладной программный интерфейс.scripting пакет принимает / возвращает типы из javax.скрипт пакета из java.scripting модуль. Итак, jdk.описание.nashorn сообщает JMPS, что любой модуль, который зависит от jdk.описание.nashorn автоматически зависит от java.модуль сценариев, а также!

теперь тот же jdk.описание.модуль nashorn использует следующую строку:

    requires jdk.dynalink;

для другого модуля пакета JDK.dynalink. Это потому, что нет экспортированных пакетов ("API") из jdk.описание.модуль nashorn использует типы из jdk.модуль dynalink. Использование jdk.dynalink от jdk.описание.nashorn-это чисто деталь реализации.


спецификация языка Java для Java 9 объясняет это в очень простых терминах. Из раздела на Модуль Зависимостей:

на requires директива указывает имя модуля, от которого зависит текущий модуль.

...

на requires ключевое слово может следовать модификатор transitive. это вызывает любой модуль, который requires текущий модуль, чтобы иметь неявно объявленную зависимость от модуль, указанный в


термин доступность неоднозначно: вы можете получить доступ к объектам без доступа к их типу. Если объект имеет тип T, который находится в пакете, который не экспортируется, и если "экспортированный" код имеет метод, возвращающий T ... Затем при вызове этого метода вы получаете дескриптор этого объекта T (и вы можете вызвать на нем любые методы, относящиеся к любому типу, известному вашему коду).

читабельности также неоднозначно: это не означает, что ваш ClassLoader будет всегда можете загрузить (неэкспортируется) класса.