NullPointerException возникает, когда Java пытается обратиться к полю, методу или элементу через ссылку, в которой находится null. Откройте первую строку stack trace, относящуюся к вашему коду, и разберите выражение слева направо. Цель не просто добавить if (x != null), а понять, почему обязательное значение не появилось или почему отсутствие значения не обработано.
Типичная строка выглядит безобидно: user.getName().trim(). Но в ней есть минимум две ссылки: user и результат getName(). Любая может быть null. Сообщение Java указывает файл и номер строки, однако не всегда автоматически объясняет бизнес-причину: пользователь не найден, поле не заполнено или метод нарушил обещание.
Берём первый кадр stack trace из своего пакета, а не последнюю строку библиотеки.
Делим длинное выражение на переменные и определяем, какая именно равна null.
Инициализируем обязательное значение или явно обрабатываем допустимое отсутствие.
Что такое null и какие операции вызывают исключение
null означает, что ссылочная переменная не указывает на объект. Это не пустая строка, не число ноль и не пустой список. Исключение появляется в момент разыменования ссылки: вызова метода, чтения поля, определения длины массива, обращения к элементу массива или синхронизации. Простое сравнение ссылки с null допустимо и само по себе не падает.
| Выражение | Результат |
|---|---|
user.getName() | NPE, если user равен null |
name.trim() | NPE, если name равен null |
items.length | NPE, если items равен null |
user == null | Безопасная проверка |
"admin".equals(role) | Безопасно при null в role |

Исключение появляется не при хранении null, а при операции через отсутствующий объект.
"" существует и имеет длину 0. Ссылка null не содержит объекта, поэтому вызвать у неё isEmpty() нельзя.Читаем stack trace и уменьшаем проблемное выражение
Stack trace читают сверху вниз до первого упоминания своего класса. Верхняя строка сообщает тип исключения, следующие показывают цепочку вызовов. Найдя файл и номер, вынесите промежуточные результаты в отдельные переменные. Это временно делает код длиннее, зато отладчик и вывод сразу показывают, где появился null.
record User(String name) {}
public class Main {
static String displayName(User user) {
String rawName = user.name(); // user может быть null
String cleanName = rawName.trim(); // rawName может быть null
return cleanName.toUpperCase();
}
public static void main(String[] args) {
User user = new User(null);
System.out.println(displayName(user));
}
}
// Пример указателя:
// Exception in thread "main" java.lang.NullPointerException
// at Main.displayName(Main.java:6)
// at Main.main(Main.java:12)- Ошибка возникла внутри
displayName, а вызов пришёл изmain. - При показанных данных объект user существует, но его компонент name содержит null.
- Исправление нужно выбирать на границе создания User или в правилах displayName, а не в println.

Начинайте с верхнего кадра своего класса: он сокращает область поиска до конкретного выражения.
Выбираем исправление по смыслу данных
Универсального оператора против null нет. Если значение обязательно, отвергните неверные данные как можно раньше. Если отсутствие допустимо, задайте явную ветку или запасное значение. Если метод поиска закономерно может ничего не найти, его контракт должен это выражать. Важен не синтаксис проверки, а понятное обещание вызывающему коду.
| Смысл значения | Подход |
|---|---|
| Обязательно | Проверить через requireNonNull на входе |
| Отсутствие допустимо | Добавить явную ветку if |
| Нужно значение по умолчанию | Подставить default осознанно |
| Поиск может ничего не вернуть | Выразить результат как Optional |
| Сравнение с константой | Вызвать equals у константы |
Практика: исправляем отображаемое имя пользователя
Допустим, имя в профиле может быть пропущено, но сам объект пользователя обязателен. Тогда метод должен отдельно защитить эти два правила: быстро отклонить null вместо User и превратить пустое имя в подпись «Гость». После исправления проверьте нормальное имя, пробелы, null-поле и null-объект.
- Добавьте
Objects.requireNonNull(user, "user must not be null")первой строкой метода. - Сохраните
user.name()в переменную и проверьте её на null до вызоваtrim(). - После trim обработайте пустую строку как «Гость», иначе верните имя в верхнем регистре.
- Проверьте
new User(" Ada "): ожидаетсяADA. - Проверьте
new User(null)иnew User(" "): в обоих случаях ожидаетсяГОСТЬ. - Передайте null вместо User: ожидается раннее исключение с вашим сообщением о нарушенном контракте.
- Обязательность объекта проверяется в одном понятном месте.
- Допустимое отсутствие имени превращается в явно выбранный результат.
- Ни один вызов метода не выполняется через ссылку, происхождение которой неизвестно.

Правильное решение зависит от контракта: запретить, обработать или выразить отсутствие.
Какие исправления маскируют NullPointerException
Быстрый патч иногда убирает текущий stack trace, но оставляет повреждённые данные. Особенно опасны проверки, которые просто прекращают работу метода, и широкие блоки catch. Через несколько шагов программа падает в другом месте, где связь с исходной причиной уже потеряна. Чините точку появления неверного состояния.
Код перестаёт падать, но часть работы молча пропускается. Сначала определите, где null допустим по правилам программы.
Так теряются тип, строка и причина. NPE обычно указывает на дефект состояния, а не на событие для обычного управления потоком.
В a.getB().getC().trim() несколько кандидатов. Вынесите шаги и проверьте контракт каждого метода.
Он полезен как явный результат поиска, но не заменяет проектирование обязательных полей и валидацию конструктора.
Без файла и номера строки разработчик исправляет похожий участок, а не реальное место падения.
null и пустая строка равны?
Нет. Пустая строка является объектом длины 0, а null не указывает на объект.
С какой строки stack trace начинать?
С первого кадра, который относится к вашему пакету и исходному файлу.
Может ли user существовать, а user.getName() вернуть null?
Да. В цепочке нужно проверять контракт каждого промежуточного результата.
Всегда ли нужна явная проверка значения на null?
Нет. Обязательные значения лучше валидировать на входе, а допустимое отсутствие обрабатывать по смыслу.
Почему catch Exception не является исправлением?
Он скрывает дефект состояния и оставляет программу с неполным результатом.
Начните с типов, методов и объектов в курсе Java. Небольшие упражнения в Кодике позволяют увидеть stack trace рядом с кодом и менять по одной строке.
Когда освоите ссылки, переходите к ошибкам коллекций Java и разбору ConcurrentModificationException. Для первого серверного проекта пригодится REST API на Spring Boot.