RU | EN | DE

1. var для локальных переменных (Java 10)

Идея. Тип выводится из правой части, только для локальных неинициализированных нельзя.

public class VarDemo {
    public static void main(String[] args) {
        var list = java.util.List.of("a", "b"); // List<String>
        for (var s : list) {
            System.out.println(s.toUpperCase());
        }
        var map = new java.util.HashMap<String, Integer>();
        map.put("x", 1);
    }
}

Пояснения. var не меняет тип, только делает запись короче.
Ошибки. var x; — нельзя без инициализации. var в полях — нельзя.
Best practices. Используй, когда тип очевиден из RHS (new HashMap<>(), фабрики, потоковые операции).

2. Switch-выражения (Java 14 permanent; 12–13 preview)

Идея. switch возвращает значение, стрелки ->, yield.

public class SwitchExprDemo {
    enum Day { MON, SAT, SUN }
    public static void main(String[] args) {
        var d = Day.SAT;
        int hours = switch (d) {
            case SAT, SUN -> 0;
            case MON -> 8;
            default -> 6;
        };
        System.out.println(hours);
    }
}

Ошибки. Смешивать старый : и новый -> в одном блоке.
Best. Предпочитай «стрелочный» синтаксис, нет fall-through и break.

3. Text Blocks """...""" (Java 15)

Идея. Многострочные строки без экранирования.

public class TextBlocksDemo {
    public static void main(String[] args) {
        String json = """
            {
              "name": "Vitaliy",
              "skills": ["Java","Spring"]
            }
            """;
        System.out.println(json);
    }
}

Ошибки. Лишние отступы — ориентируйся на «общий отступ» закрывающих """.
Best. Для SQL/JSON/XML — читаемость + formatted(...) для подстановок.

4. Records (Java 16)

Идея. Компактные неизменяемые DTO: equals/hashCode/toString и аксессоры генерятся.

public record User(String username, int level) {
    public User {
        if (level < 0) throw new IllegalArgumentException("level >= 0");
    }
    public String display() { return username + ":" + level; }
}

Ошибки. Мутация через отражение/нестандартные трюки — ломает идею records.
Best. Храни «данные без логики состояния», валидация — в компактном конструкторе.

5. Pattern matching для instanceof (Java 16)

Идея. Сопоставление с образцом сразу даёт переменную нужного типа.

static int len(Object o) {
    if (o instanceof String s) return s.length();
    if (o instanceof java.util.Collection<?> c) return c.size();
    return -1;
}

Ошибки. Тень переменных: не переопределяй имя s во вложенной области.
Best. Убирай касты: меньше шума и NPE.

6. Sealed classes/interfaces (Java 17)

Идея. Ограниченный полиморфизм: кто может наследоваться.

public sealed interface Shape permits Circle, Rect { }
 
public final class Circle implements Shape {
    public final double r;
    public Circle(double r) { this.r = r; }
}
 
public non-sealed class Rect implements Shape { // дальше можно наследовать свободно
    public final double w, h;
    public Rect(double w, double h) { this.w = w; this.h = h; }
}

Ошибки. Забыть permits (если не все в одном файле/пакете).
Best. Комбинируй с switch + паттерны — исчерпывающие ветки.

7. Pattern matching для switch + Guarded patterns (Java 21 permanent)

Идея. switch по типам и условиям, исчерпывающие проверки.

static String render(Object o) {
    return switch (o) {
        case null -> "null";
        case String s when s.isBlank() -> "empty string";
        case String s -> "str: " + s;
        case Integer i && i > 0 -> "pos int: " + i;
        case java.util.List<?> lst -> "list size=" + lst.size();
        default -> "other";
    };
}

Ошибки. Непокрытые варианты (добавляй default/null).
Best. Для sealed-иерархий default часто не нужен — компилятор следит за полнотой.

8. Record patterns (Java 21 permanent)

Идея. Распаковывать record прямо в переменные/ветки switch.

record Point(int x, int y) {}
 
static int manhattan(Object o) {
    return switch (o) {
        case Point(int x, int y) -> Math.abs(x) + Math.abs(y);
        default -> -1;
    };
}

Ошибки. Несоответствие арности/порядка компонент.
Best. Используй вместе с sealed для чистого pattern-based кода.

9. Unnamed variables & patterns (_) (Java 22 permanent)

Идея. _ как «я осознанно игнорирую».

public class UnderscoreDemo {
    public static void main(String[] _ /* игнор аргументов */) {
        Object o = "java";
        if (o instanceof String _) { // matched, но значение не нужно
            System.out.println("It is String");
        }
    }
}

Ошибки. _ нельзя использовать как обычное имя переменной.
Best. Помечай «неиспользуемые» параметры/паттерны, чтобы не плодить заглушки.

10. Compact Source Files & Instance main (Java 25, финал ветки unnamed/implicit)

Идея. Мини-программы без явного класса в исходнике; main — нестатический.

// File: Hello.java  (Java 25)
void main() { System.out.println("Hello, Java 25!"); }

Компилятор сам «оборачивает» в класс при сборке. Ошибки. Использовать одновременно обычный класс и «компактный» стиль в одном файле. Best. Отлично для примеров, тулзов, сниппетов.

11. Flexible Constructor Bodies (Java 25 permanent)

Идея. В конструкторах можно выполнять код до явного super(...)/this(...) (с ограничениями порядка и инициализации).

class Base {
    Base(String id) { System.out.println("Base " + id); }
}
class Child extends Base {
    Child(String raw) {
        String id = raw.trim().toUpperCase(); // логика до super(...)
        super(id);
        System.out.println("Child ready");
    }
}

Ошибки. Обращение к this/переопределённым методам до корректной инициализации — избегай побочек.
Best. Держи раннюю логику чистой/детерминированной (парсинг, валидация, нормализация).

12. Module system (Java 9) — только синтаксис языка

Идея. module-info.java описывает границы.

module com.example.core {
    exports com.example.api;
    requires java.sql;
}

Ошибки. «Серые» зависимости, забытый exports.
Best. Явно фиксируй публичную поверхность через exports/opens.

13. Module Import Declarations (Java 25 permanent)

Идея. Импорт всего модуля «в пространство видимости» исходника.

import module java.base;
import module java.sql;
 
public class ModuleImportDemo {
    public static void main(String[] args) {
        System.out.println(java.time.Instant.now());
        try (var conn = java.sql.DriverManager.getConnection("jdbc:h2:mem:db")) {
            System.out.println(conn.getMetaData().getURL());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Ошибки. Путать с import package.*; — это другая механика (уровень модуля).
Best. Используй в модульных приложениях для явности зависимостей в исходниках.

14. Примитивы в паттернах/instanceof/switch (Java 25 — всё ещё preview)

Идея. Матчить по примитивам без боксинга.

// Компилируй с --enable-preview --release 25
static String describeInt(int x) {
    return switch (x) {
        case int i && i > 0 -> "positive";
        case 0 -> "zero";
        default -> "negative";
    };
}

Ошибки. Забыть --enable-preview во время компиляции/запуска.
Best. Пока экспериментируй точечно; следи за финализацией в 26+.

Частые ошибки миграции (8 → 25)

  • Путают switch-выражение (нужно значение) и старый switch (оператор).
  • Используют record как «бог-объект» с изменяемыми полями через мутаторные трюки — ломает контракт.
  • sealed + switch: забывают добавить новые подклассы — компилятор начнёт ругаться на неохваченность.
  • Text Blocks с «лесенкой» отступов — выровняй закрывающие кавычки.

Рекомендации по стилю

  • Включай pattern matching для ветвления по типу/форме данных — меньше кастов и if-else.
  • Для DTO — records; для иерархий с закрытым набором — sealed.
  • Для шаблонного текста — text blocks; для вычисляемого текста — switch-выражения + formatted(...).
  • Новые учебные/CLI-сниппеты демонстрируй в стиле Compact Source Files (Java 25).