← Назад к вопросам

Что сделали с NullPointerException в Java с версии 11 по 17

2.0 Middle🔥 141 комментариев
#JVM и управление памятью#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Улучшения NullPointerException в Java 11-17

Контекст проблемы

NullPointerException — одна из самых частых ошибок в Java. Раньше при возникновении этого исключения разработчик получал лишь строку кода, но не понимал, какой именно объект был null. С Java 11 ситуация стала меняться.

Java 14: Helpful NullPointerExceptions

Самое значительное улучшение произошло в Java 14 с введением Helpful NullPointerExceptions (HelpfulNPE). Это была долгожданная фича, предложенная в JEP 358.

Включение функции

Функция по умолчанию выключена. Включить её можно через JVM флаг:

java -XX:+ShowCodeDetailsInExceptionMessages MyProgram

Пример до Java 14

public class Person {
    private String name;
    private Address address;
    
    public String getCityName() {
        return address.getCity().getName();  // Какой null?
    }
}

// Вывод при NPE:
// Exception in thread "main" java.lang.NullPointerException
//    at Person.getCityName(Person.java:8)
// Не понимаем: address null? city null?

Пример с Java 14+

// С флагом -XX:+ShowCodeDetailsInExceptionMessages
// Вывод:
// Exception in thread "main" java.lang.NullPointerException: 
// Cannot invoke method "getCity()" because "this.address" is null
//    at Person.getCityName(Person.java:8)

// Или если city null:
// Cannot invoke method "getName()" because the return value of 
// "getCity()" is null

Как это работает

JVM анализирует bytecode и определяет:

  1. Какой объект/переменная была null
  2. На каком шаге цепочки вызовов произошла ошибка
  3. Выводит полное описание проблемы на русском

Java 15: Records и Pattern Matching

В Java 15 добавлены Records, которые помогают избежать NPE через инкапсуляцию полей:

public record Person(String name, Address address) {}

// Теперь поля final и не могут быть изменены на null случайно
var person = new Person("John", new Address("New York"));

Java 16-17: Pattern Matching для instanceof

Работает с null-проверками:

public void process(Object obj) {
    // Избегаем null check через pattern matching
    if (obj instanceof String str) {
        System.out.println(str.toUpperCase());
    }
}

// Альтернатива с var и null-проверкой:
if (obj instanceof String str && str != null) {
    System.out.println(str);
}

Optional как альтернатива

С Java 8+ рекомендуется использовать Optional вместо null:

// Плохо
public Address getAddress() {
    return null;  // Может быть null
}

// Хорошо
public Optional<Address> getAddress() {
    return Optional.ofNullable(address);
}

// Использование
person.getAddress()
    .map(Address::getCity)
    .map(City::getName)
    .ifPresent(System.out::println);

Текущее состояние (Java 21+)

С Java 21 (LTS версия) рекомендуемые практики:

  1. Всегда включай ShowCodeDetailsInExceptionMessages
  2. Используй Optional для явного обозначения nullable полей
  3. Используй Records для immutable данных
  4. Применяй Pattern Matching для безопасных типопреобразований
// Современный подход
public class PersonService {
    public String getCityName(Person person) {
        return person.address()
            .flatMap(addr -> addr.city())
            .map(City::name)
            .orElse("Unknown");
    }
}

Итог

Java 14 привнесла Helpful NullPointerExceptions — детальные сообщения об ошибках. Java 15-17 добавили Records, Pattern Matching и усилили поддержку Optional. В совокупности эти фичи делают код более безопасным и снижают вероятность NPE.