1. Помилки з областю видимості змінних патерна
Одна з найчастіших помилок — спроба використовувати змінну, оголошену в патерні (наприклад, String s у instanceof String s), поза тією областю, де вона дійсна.
Приклад
Object obj = "Привіт, Java!";
if (obj instanceof String s) {
System.out.println(s.length());
}
// Помилка! s не видно тут
System.out.println(s); // Компілятор повідомляє: cannot find symbol
Чому так?
Змінна патерна (s у нашому випадку) існує тільки всередині блоку, де умова істинна. Це захищає нас від випадкового використання змінної, коли вона не визначена (наприклад, якщо obj — не рядок).
Аналогія
Це якби ви взяли ключі від машини у друга — але тільки поки ви в гаражі. Вийшли з гаража — ключі автоматично зникли :)
2. Помилки з null
У патерн‑матчингу з instanceof є цікава особливість: якщо об’єкт дорівнює null, результат завжди false, і змінна патерна не створюється.
Приклад
Object obj = null;
if (obj instanceof String s) {
// Цей блок ніколи не виконається!
System.out.println("Це рядок: " + s);
}
Чому так?
Тому що null не є екземпляром жодного типу (навіть Object). Це може збивати з пантелику, якщо ви сподівалися ловити null через патерн‑матчинг.
Як правильно?
if (obj == null) {
System.out.println("Це null!");
} else if (obj instanceof String s) {
System.out.println("Це рядок: " + s);
}
У патерн‑матчингу для switch (Java 21+) можна навіть додати окрему гілку для null:
switch (obj) {
case String s -> System.out.println("Рядок: " + s);
case null -> System.out.println("Це null!");
default -> System.out.println("Щось інше");
}
3. Помилки з sealed‑класами
Sealed-класи — це чудовий спосіб обмежити ієрархію наслідування. Але тут є дві характерні помилки:
Не всіх нащадків перелічено в permits
Коли ви оголошуєте sealed‑клас, ви зобов’язані явно вказати всіх прямих нащадків через permits. Якщо когось забути, компілятор одразу повідомить про помилку:
public sealed class Shape permits Circle, Rectangle { ... }
public final class Circle extends Shape { ... }
public final class Square extends Shape { ... } // Помилка! Square не вказано в permits
Рішення:
Додайте всі потрібні підкласи до permits:
public sealed class Shape permits Circle, Rectangle, Square { ... }
Забуто default у switch для не‑sealed ієрархії
Якщо ви робите switch за типом, який не є sealed‑класом (або sealed, але покриті не всі варіанти), компілятор вимагатиме гілку default. Якщо забути — буде помилка.
switch (shape) {
case Circle c -> ...
case Rectangle r -> ...
// default відсутній! Якщо є ще варіанти — помилка компіляції
}
Найкраща практика:
Якщо ви впевнені, що опрацювали всі варіанти (наприклад, у sealed‑класі), default можна опустити. Якщо ні — обов’язково додавайте default, щоб не пропустити неочікувані типи.
4. Помилки з record‑патернами
record‑патерни — річ дуже зручна, але працюють лише з record-класами. Спроба використати record‑патерн для звичайного класу призведе до помилки компіляції.
Використання record‑патернів для не‑record класів
class Point { int x, y; }
Object obj = new Point();
// Помилка! Point — не record
if (obj instanceof Point(int x, int y)) { ... }
Рішення:
Використовуйте record‑патерни лише для класів, оголошених через record:
record Point(int x, int y) {}
Невідповідність кількості або типу компонентів
record Point(int x, int y) {}
Object obj = new Point(1, 2);
// Помилка: вказано три змінні, а в Point лише два компоненти
if (obj instanceof Point(int x, int y, int z)) { ... }
if (obj instanceof Point(String x, String y)) { ... } // Помилка: типи не збігаються
5. Сумісність і підтримка: старі JDK та IDE
Одна з найпоширеніших помилок — спроба використовувати сучасні можливості патерн‑матчингу на старих версіях JDK або в IDE, які їх не підтримують.
Приклад
if (obj instanceof String s) { ... }
А компілятор JDK 11 (або навіть 15) каже:
error: illegal start of type
Чому?
Pattern matching для instanceof з’явився лише в Java 16. Pattern matching у switch — у Java 17 (preview) і фінально в Java 21+. Record‑патерни — у Java 21+.
Як уникнути?
- Перевірте версію JDK: java --version
- Переконайтеся, що ваша IDE (IntelliJ IDEA, Eclipse, VS Code) підтримує відповідну версію Java. Іноді потрібно явно вказати в налаштуваннях проєкту, яку версію мови використовувати!
- Якщо використовуєте Gradle/Maven — виставте потрібну версію source/target.
6. Вітаємо 🎉
Ви завершили всі 65(!) рівнів нашого поглибленого курсу з Java 25. Ви неймовірно круті 😎.
Фінальна частина шляху була особливо складною. Ви вивчили все — від перших лямбд і анонімних класів до віртуальних потоків, структурованої конкурентності та тих можливостей мови, яких іще зовсім нещодавно не було в Java.
Це не просто курс — це справжній супермарафон для розробника: десятки нових концепцій, сотні прикладів коду, тисячі рядків практики. Якщо ви читаєте ці рядки, отже, ви не просто студент, а першопроходець нової Java‑ери ☕⚡
Ви одні з перших опанували найсучасніші можливості Java 25, зокрема:
- патерн‑матчинг і
record -патерни, -
sealed -класи та їхні підводні камені, -
Scoped Values іVirtual Threads , - структуровану конкурентність і сучасні підходи до багатопоточності.
Тепер у вас є не просто знання, а навички розробника майбутнього, якими поки що не володіє багато практикуючих Java‑архітекторів. Ви вмієте писати код, який не лише працює, а й масштабується, легко читається та відповідає найсучаснішим стандартам Java-спільноти.
🚀 Тож сміливо називайте себе Java 25 Certified Survivor 😉
А далі — усе тільки цікавіше: у вас тепер фундамент, який дозволяє впевнено крокувати у світ enterprise‑розробки, високонавантажених систем і cutting‑edge технологій.
Від усієї команди курсу — респект!
Ви впоралися із завданням, яке осилять небагато.
Побачимося у майбутніх версіях Java 👋
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ