Что такое модули в Java (JPMS) и являются ли они частью одного проекта?

Ответ

Модули в Java — это функциональные единицы инкапсуляции, введенные Java Platform Module System (JPMS) в Java 9. Они описываются файлом module-info.java и позволяют явно декларировать зависимости (requires) и публичный API (exports).

Являются ли модули частью одного проекта? Да, модули обычно являются частью одного проекта, но они организуют его код в логически изолированные компоненты с четкими границами. Однако модуль также может быть самостоятельной библиотекой, используемой в разных проектах.

Цели модулей:

  • Надежная инкапсуляция: Скрытие внутренних пакетов от внешнего мира.
  • Явное объявление зависимостей: Устранение проблем classpath.
  • Улучшение структуры приложения: Разделение на компоненты.

Пример структуры проекта с двумя модулями:

my-application/
├── module-a/
│   ├── src/main/java/
│   │   ├── com.example.a.internal/  // Внутренний, не экспортируемый пакет
│   │   ├── com.example.a.api/       // Публичный API
│   │   └── module-info.java
│   └── pom.xml (или build.gradle)
└── module-b/
    ├── src/main/java/
    │   ├── com.example.b/
    │   └── module-info.java
    └── pom.xml

Содержимое module-info.java:

// module-a/module-info.java
module com.example.module.a {
    exports com.example.a.api; // Только этот пакет виден извне
    // Пакет 'internal' скрыт
}

// module-b/module-info.java
module com.example.module.b {
    requires com.example.module.a; // Явная зависимость от модуля A
    // Теперь код в module-b может использовать только public-типы из com.example.a.api
}

Вывод: Модули — это способ организации кода внутри проекта в независимые, хорошо определенные компоненты с контролируемыми зависимостями, что упрощает сборку, тестирование и поддержку.

Ответ 18+ 🔞

А, модули в Java, блядь! Ну это ж классика, ёпта! Пришли они, эти мартышлюшки, в девятой джаве и начали тут всем мозги ебать.

Смотри, представь себе обычный проект — это как коммуналка, блядь. Все классы в одном общем classpath-сортире, друг на друге сидят, друг у друга штаны срисовывают, а кто кого использует — нихуя не понятно. Пиздец бардак, короче.

А модули — это когда эту коммуналку расселяют, блядь, по отдельным, ёбаным, квартирам-модулям. У каждой квартиры своя дверь (файл module-info.java), и чтобы к соседу за солью сходить, надо сначала в дверь постучаться и крикнуть requires, а то не пустят, хитрая жопа!

Так они в одном проекте или нет? Да в одном, блядь, конечно! Это ж как семья: живут в одной квартире, но у каждого своя комната с замком. Проект my-application, а в нём две комнатушки-модуля: module-a и module-b. Каждый со своим уставом, блядь.

А зачем весь этот цирк, спросишь? А затем, сука, чтобы не было вот этого:

  1. Инкапсуляция, ёпта! Раньше сделаешь класс public — и всё, любой урод из соседнего jar-ника может к нему прицепиться. А теперь? В module-info.java пишешь, какие пакеты на публику (exports), а какие — твои личные, внутренние дела, про которые никто, блядь, не узнает. Чистая магия!
  2. Зависимости явные! Раньше classpath соберёшь — и молишься, чтобы всё подцепилось. А теперь если модулю B нужен модуль A, он это явно прописывает: requires com.example.module.a. Нет записи — нихуя не получишь, хоть обоссысь! Красота, блядь.
  3. Структура, ядрёна вошь! Большой проект сразу видно, кто от кого зависит. Собрать, протестить, поддерживать — в разы легче. Не тащишь в сборку три тонны левых библиотек, которые на самом деле не нужны.

Вот смотри, как они живут:

my-application/                     <-- Это весь наш дом, проект
├── module-a/                       <-- Квартира №1. Мужик-отшельник, там паяльник и микросхемы
│   ├── src/main/java/
│   │   ├── com.example.a.internal/  // Его похабный журнал под подушкой. НИКОМУ НЕ ПОКАЗЫВАЕТ!
│   │   ├── com.example.a.api/       // А вот это его парадная дверь. Тут он гостей принимает.
│   │   └── module-info.java         // Правила въезда в квартиру!
│   └── pom.xml
└── module-b/                       <-- Квартира №2. Тусовщик, ему всё время соль у первого занимать
    ├── src/main/java/
    │   ├── com.example.b/           // Его хата
    │   └── module-info.java         // И его правила: "Разрешаю себе зависеть от того мудака с паяльником"
    └── pom.xml

А вот и сами правила, блядь, смотри:

// module-a/module-info.java
module com.example.module.a {
    exports com.example.a.api; // Эй, мир! Заходите, но только в эту прихожую (пакет api)!
    // А про внутренний пакет internal забудьте как страшный сон. Его нет.
}

// module-b/module-info.java
module com.example.module.b {
    requires com.example.module.a; // Я, блядь, официально признаю, что завишу от соседа!
    // Теперь я могу использовать только то, что он в прихожей (api) выставил.
    // За его похабный журнал (internal) мне наедет, если сунусь.
}

Вывод, блядь? Модули — это не какие-то отдельные вселенные. Это просто способ навести пиздатый порядок в своём же, ёбта, проекте. Разделил код на логические куски, нарисовал между ними чёткие границы — и живи спокойно, не боясь, что завтра какая-нибудь левая библиотека полезет в твои приватные поля, как в свою хату. Удобно, чё.