Подтвердить что ты не робот

Какая разница между требованиями и требует переходных операторов в декларации модуля Java 9

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

Например:

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

Ответ 1

Чтение читаемости

Если модуль модуля requires выпивает, то система модуля...

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

Точно так же, если bar requires transitive drink - напиток должен присутствовать, его можно прочитать и получить. Фактически, для бара и напитка ключевое слово transitive ничего не меняет.

Подразумеваемая читаемость

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

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

Использовать случаи

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

// in module _bar_
public class Bar {

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

}

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

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

клиент требует, чтобы в баре требовался напиток - но как клиент читает напиток?

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

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

Ответ 2

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

Если один модуль экспортирует пакет, содержащий тип, подпись которого относится к пакету во втором модуле, тогда декларация первый модуль должен включать зависимость 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
}

Ответ 3

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

Цитирование цитаты

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

Короче:

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

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

Ответ 4

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

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

Он имеет следующую строку:

requires transitive java.scripting;

Это связано с тем, что jdk.scripting.nashorn собственный API в jdk.scripting.api.scripting package принимает/возвращает типы из javax.script пакета java.scripting. Поэтому jdk.scripting.nashorn сообщает JMPS, что любой модуль, который зависит от jdk.scripting.nashorn, автоматически зависит от модуля java.scripting!

Теперь тот же модуль jdk.scripting.nashorn использует эту строку:

    requires jdk.dynalink;

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

Ответ 5

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

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

...

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

Другими словами:

  • если модуль X requires модуль Y,
  • и модуль Y requires transitive модуль Z,
  • тогда модуль X также (неявно) requires модуль Z.