JavaRush /Курсы /JAVA 25 SELF /Введение в модули: зачем нужны

Введение в модули: зачем нужны

JAVA 25 SELF
60 уровень , 0 лекция
Открыта

1. Проблемы старого подхода

«Classpath party»: когда все на одной кухне

До появления модулей в Java (в девятой версии) весь код приложения, библиотеки и зависимости сваливались в одну большую кучу — classpath. Границ между библиотеками фактически не было: любой класс, попавший в classpath, мог быть найден и использован кем угодно.

Появлялись конфликты имён: две библиотеки содержат класс с одинаковым полным именем, например com.example.Util — выбирался «какой-то один», а вы узнавали о проблеме уже по странному поведению в рантайме.

Классика жанра — dependency hell: одна библиотека требует логгер версии 1.2, другая — 1.3, а в classpath оказываются обе. JVM не знает, что подхватить, и вы ловите загадочный NoSuchMethodError.

И ещё: даже если класс объявлен как public, но предназначен для внутренних нужд библиотеки, другой код всё равно может его использовать — и сломать себе что-нибудь в процессе. Большие проекты превращались в минное поле, а сопровождение — в приключение.

2. Что такое модуль в Java?

Модуль: как коробка с дырочками

В Java 9 появилась модульная система (JPMS). Модуль — это коробка с классами и пакетами, в которой вы сами делаете «дырочки»: явным образом указываете, что показываете наружу (exports), а что прячете внутри. И да: даже public-класс не виден другим модулям, если его пакет не экспортирован.

Формальное определение

Модуль — логическая единица разбиения кода, объединяющая связанные пакеты и классы. Каждый модуль явно объявляет:

  • что он экспортирует — делает доступным другим модулям (exports);
  • и что он импортирует — от каких других модулей зависит (requires).

Ключевые свойства модуля:

  • Явные границы. Чётко определено, что доступно извне, а что нет.
  • Явные зависимости. Модуль не «видит» другой модуль без явного requires.
  • Изоляция. Внутренние детали полностью скрываемы от внешнего мира.

3. Преимущества модульности

Улучшенная инкапсуляция

Появился новый уровень видимости — на уровне модуля. Даже если класс public, но его пакет не экспортируется, он виден только внутри модуля. Внутренности библиотеки больше не «просачиваются» наружу.

Явное описание зависимостей

Нужные зависимости перечисляются в module-info.java. Компилятор и IDE заранее предупредят, если вы забыли указать модуль, от которого зависите.

Улучшенная безопасность и надёжность

Ограничение доступа к внутренним API усложняет случайное или преднамеренное вмешательство. Это критично для крупных библиотек и платформенных модулей.

Возможность создания «урезанных» JRE

С помощью jlink можно собрать минимальный рантайм только из нужных модулей. В облаке и embedded-сценариях это экономит дисковое пространство и память.

Бонус: ускорение старта и уменьшение размера

Загружаются не все модули, а только реально используемые — приложения стартуют быстрее и потребляют меньше ресурсов.

4. Где используются модули

В стандартной библиотеке Java

Начиная с Java 9, сама платформа модульна. Примеры:

  • java.base — базовый модуль (обязателен для любой программы).
  • java.sql — работа с базами данных.
  • java.xml — работа с XML.

Если вы не используете XML, модуль java.xml даже не попадёт в ваш рантайм.

В крупных приложениях и библиотеках

Must-have для корпоративных систем, где десятки команд разрабатывают части монорепозитория. Модульность уменьшает конфликты и упрощает сопровождение.

В собственных проектах

Даже в pet-проекте модули помогают тренировать архитектурное мышление и держать код в порядке, избегая «спагетти».

5. Краткий обзор синтаксиса: module-info.java

Самое главное — файл module-info.java

Файл module-info.java лежит в корне исходников модуля и объявляет его границы и зависимости.

module my.awesome.module {
    exports com.example.api;        // Экспортируемый пакет
    requires java.sql;              // Зависимость от стандартного модуля
}

Основные ключевые слова:

  • module <имя> — объявляет модуль.
  • exports <пакет> — делает пакет доступным другим модулям.
  • requires <модуль> — объявляет зависимость от другого модуля.

Минимальный пример:

module com.myproject.core {
    exports com.myproject.core.api;
}

Пример с зависимостью:

module com.myproject.app {
    requires com.myproject.core;
    requires java.sql;
}

Дополнительные возможности (кратко): для рефлексии есть opens, для сервисов — uses и provides ... with ... (подробно — в продвинутых лекциях).

6. Полезные нюансы

Модули — это как «паспорта» для классов. Раньше любой класс с визой public мог «путешествовать» по приложению. Теперь нужен ещё и модульный «паспорт» — экспорт пакета (exports). Без него класс остаётся «дома».

Dependency hell — это реальный термин. Если видели ClassNotFoundException: com.google.common.base.Strings, вы там побывали. Модули призваны разогнать этих «чертей» строгими границами и зависимостями.

Вся Java теперь модульная. Даже если вы не пишете свои модули, платформа уже разбита на десятки. Попробуйте команду:

java --list-modules

Как это влияет на разработку

Вы явно управляете видимостью кода, и внутренние пакеты больше не становятся доступны всем «по случайности». IDE и компилятор ловят ошибки раньше: забыли объявить зависимость — проект не соберётся. Поддержка больших систем упрощается: проще понять, кто от кого зависит и что сломается при изменениях.

7. Типичные ошибки при переходе на модули

Ошибка №1: забыли экспортировать пакет, но класс public. Вы объявили класс как public, но не экспортировали его пакет — другие модули не смогут его использовать. Компилятор сообщит: «Пакет не экспортируется модулем».

Ошибка №2: не объявили зависимость через requires. Вы используете тип из другого модуля, но забыли добавить requires в module-info.java. Итог — ошибка компиляции «модуль не может найти нужный класс».

Ошибка №3: дублирующиеся имена модулей. В большом проекте два модуля случайно получили одинаковое имя. JVM такого не прощает — переименуйте и соблюдайте единый нейминг.

Ошибка №4: забыли про стандартные модули. Например, используете JDBC, но не добавили requires java.sql;. В Java 8 «и так было видно», а в 9+ — нет.

Ошибка №5: попытка использовать внутренний класс другого модуля. Если пакет не экспортируется, даже public-класс остаётся невидимым извне. Экспортируйте пакет или вынесите API в «публичный» слой.

1
Задача
JAVA 25 SELF, 60 уровень, 0 лекция
Недоступна
Минимальное сердце модуля 🫀
Минимальное сердце модуля 🫀
1
Задача
JAVA 25 SELF, 60 уровень, 0 лекция
Недоступна
Открытие шлюза к библиотеке 🔑
Открытие шлюза к библиотеке 🔑
Комментарии (1)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Ioanna Polyak Уровень 43
10 декабря 2025
60💪🤜🤛