Перейти к основному содержимому

Современные конструкции Java

Разработчику Архитектору

Современные конструкции Java

Язык после Java 8 получил конструкции, которые сокращают шаблонный код и делают модели данных и иерархии типов явными. Ниже — обзор с Java 14 по 21, без привязки к конкретному LTS: проверяйте версию JDK в структуре проектов.

Связанные темы: ООП, ключевые слова, Stream API.


Локальный вывод типа var (Java 10+)

var list = new ArrayList<String>(); // ArrayList<String>
var path = Path.of("config.yml"); // Path

var — только для локальных переменных с инициализатором. Тип выводится компилятором, в байт-коде — обыный явный тип.

Не используйте var, если тип неочевиден из правой части (var x = service.find() — плохо).


record (Java 16+)

Неизменяемый носитель данных с автоматическими equals, hashCode, toString, геттерами:

public record Point(int x, int y) {
public Point {
if (x < 0 || y < 0) throw new IllegalArgumentException();
}
}
recordКласс с полями
Мало кода, семантика «значение»Гибкость, изменяемость, наследование
Нельзя наследовать классыОбычная иерархия
Подходит для DTO, команд, событийСущности с поведением

Record может реализовывать интерфейсы и содержать статические члены; компактный конструктор валидирует поля.

В Spring / JPA records часто используют как DTO; сущности БД по-прежнему часто — классы с прокси Hibernate.


sealed-классы и интерфейсы (Java 17+)

Ограничивают, кто может наследовать или реализовать тип:

public sealed interface Shape permits Circle, Rectangle { }

public record Circle(double radius) implements Shape { }

public record Rectangle(double width, double height) implements Shape { }
Модификатор подтипаСмысл
finalДальнейшее наследование запрещено
sealedСнова ограниченный список permits
non-sealedОткрыть ветку иерархии

Польза: исчерпываемые варианты (результат операции, тип сообщения), безопасный switch по типам.


Pattern matching

instanceof (Java 16+):

if (obj instanceof String s && !s.isBlank()) {
System.out.println(s.toUpperCase());
}

switch по типу (Java 17+, расширяется в 21+):

static double area(Shape shape) {
return switch (shape) {
case Circle c -> Math.PI * c.radius() * c.radius();
case Rectangle r -> r.width() * r.height();
};
}

Компилятор проверяет полноту для sealed-иерархий: если все подтипы известны, default не обязателен.

switch-выражение (Java 14+) возвращает значение:

String level = switch (code) {
case 1, 2 -> "low";
case 3 -> "medium";
default -> "high";
};

Стрелки -> без fall-through; классический case X: с break по-прежнему доступен.


Текстовые блоки и formatted

См. строки: """ ... """ и "{}".formatted(args).


Вспомогательные API

  • Optional — см. Stream API.
  • List.of, Map.of, Set.of — неизменяемые коллекции фиксированного размера.
  • Objects.requireNonNullElse — null-safe значения по умолчанию.

Что выбрать в новом коде

ЗадачаРекомендация
DTO ответа APIrecord
Закрытый набор вариантовsealed + switch
Богатая доменная сущностьобычный класс, инкапсуляция
Анонимный коллбэклямбда вместо анонимного класса (особенности)
Много полей с наследованиемкласс, не record

Версии и совместимость

  • Укажите release / source / target в Maven/Gradle под LTS вашей команды.
  • Multi-release JAR — если нужны разные реализации под разные JDK (конфигурации).
  • Не используйте preview-фичи в production без --enable-preview и плана миграции.

Связанные материалы


См. также

Другие статьи этого же раздела в боковом меню (как на странице «О разделе»).