5 проверенных способов защиты от NullPointerException в Java
Для кого эта статья:
- Для начинающих Java-разработчиков
- Для опытных разработчиков, желающих улучшить качество своего кода
Для технических лидеров и менеджеров проектов в области программирования
Работа со строками — хлеб с маслом программирования на Java, и недостаточное внимание к проверке на null или пустоту может привести к неприятным NullPointerException. Приходилось ли вам видеть, как падает продакшн только потому, что где-то в коде разработчик забыл проверить строку перед вызовом метода? 💥 Я расскажу о пяти проверенных способах обезопасить ваш код от таких ситуаций, подробно разберу каждый метод и поделюсь практическими рекомендациями, когда какой подход использовать.
Столкнулись с проблемами при работе со строками в Java? На Курсе Java-разработки от Skypro вы не только освоите надёжные методы проверки строк на null и пустоту, но и получите комплексное понимание работы с данными. Наши студенты уже на второй неделе обучения перестают допускать ошибки, связанные с NullPointerException, благодаря детальному разбору кодовых паттернов и практике с реальными задачами под руководством действующих разработчиков.
Почему важна проверка строк на null и пустоту в Java
Проверка строк на null и пустоту — это не просто хорошая практика, а необходимость для создания надежного и устойчивого к ошибкам кода. Java, будучи строго типизированным языком, не прощает небрежности при работе с объектами, особенно со строками, которые повсеместно используются в большинстве приложений.
Отсутствие проверок может привести к нескольким серьезным проблемам:
- NullPointerException — самое распространенное исключение в Java, возникающее при попытке вызвать метод или получить доступ к свойству null-объекта
- Логические ошибки — когда пустая строка интерпретируется иначе, чем предполагалось в бизнес-логике
- Проблемы с производительностью — излишние или неэффективные проверки могут замедлить работу приложения
- Уязвимости безопасности — непроверенные входные данные могут привести к эксплойтам в веб-приложениях
Алексей Петров, ведущий Java-разработчик
Однажды мы запустили новую версию платежной системы, где я отвечал за модуль обработки платежей. В 3 часа ночи меня разбудил звонок — система упала. Оказалось, что в блоке обработки адреса доставки чека не была реализована проверка на null. Пользователь не указал email, сервис попытался вызвать метод trim() для null-объекта, и всё рухнуло.
Мы быстро исправили ошибку, добавив простую проверку:
JavaСкопировать кодif (email != null && !email.isEmpty()) { emailService.sendReceipt(email.trim(), receipt); }После этого случая в нашей команде появилось правило: любая строка, приходящая извне, должна проходить двойную проверку — на null и на пустоту.
| Тип ошибки | Причина | Последствия |
|---|---|---|
| NullPointerException | Вызов метода у null-ссылки | Крах приложения, прерывание работы пользователя |
| Логические ошибки | Путаница между null и пустой строкой | Неправильная бизнес-логика, трудно отслеживаемые баги |
| Ошибки при конкатенации | Попытка объединения со строкой null | Строка с текстом "null" вместо ожидаемого значения |

Метод 1: Проверка строки через условный оператор if
Самый базовый и понятный способ проверки строк — использование условного оператора if с явной проверкой на null и пустоту. Этот метод понятен даже начинающим разработчикам и не требует знания специфичных методов Java API.
Стандартная проверка выглядит так:
if (str != null && !str.equals("")) {
// Безопасно работаем со строкой
}
Более компактный вариант с использованием метода equals из объекта-константы:
if (str != null && !"".equals(str)) {
// Безопасно работаем со строкой
}
Второй вариант имеет небольшое преимущество — он менее подвержен ошибкам, поскольку исключает случайную замену операторов сравнения (== вместо !=).
Преимущества метода:
- Понятность — код читается практически как обычное предложение
- Универсальность — работает во всех версиях Java
- Гибкость — легко модифицируется для дополнительных условий
Недостатки:
- Многословность — требует явного написания двух условий
- Риск ошибок — можно случайно перепутать порядок проверок
- Неоптимальность — при частом использовании создает повторяющийся код
Мария Соколова, технический лид
В нашей команде новичок допустил классическую ошибку, которая чуть не стоила нам контракта с крупным клиентом:
JavaСкопировать кодif (!str.equals("") && str != null) { // Код, который никогда не выполнится при null }Логика проверки была нарушена — сначала проверялось равенство пустой строке, а потом уже null. Если str == null, то первое же условие вызывало NullPointerException.
Мы внедрили два важных правила: порядок проверок должен быть строго от null к другим условиям, а для повторяющихся проверок мы создали утилитный класс StringUtils с методами:
JavaСкопировать кодpublic static boolean isNullOrEmpty(String str) { return str == null || str.isEmpty(); } public static boolean isNotNullOrEmpty(String str) { return !isNullOrEmpty(str); }Это позволило нам избегать подобных ошибок и существенно сократить код.
Метод 2: Использование String.isEmpty() для пустых строк
Метод isEmpty() был добавлен в Java 6 и предоставляет более элегантный способ проверки строки на пустоту. Он проверяет, имеет ли строка длину 0, но не решает проблему проверки на null.
Типичное использование выглядит так:
if (str != null && str.isEmpty()) {
// Строка существует, но пуста
}
if (str != null && !str.isEmpty()) {
// Строка существует и не пуста
}
Важно понимать, что isEmpty() возвращает true только для строк с нулевой длиной. Строки, содержащие только пробельные символы, не считаются пустыми.
| Выражение | Результат для str = null | Результат для str = "" | Результат для str = " " | Результат для str = "abc" | ||
|---|---|---|---|---|---|---|
| str.isEmpty() | NullPointerException | true | false | false | ||
| str != null && str.isEmpty() | false | true | false | false | ||
| str == null | str.isEmpty() | true | true | false | false |
Преимущества метода:
- Читаемость — метод имеет говорящее название
- Эффективность — внутренняя реализация оптимизирована в JVM
- Стандартность — часть официального API Java
Недостатки:
- Не обрабатывает null — все еще требуется отдельная проверка
- Не учитывает строки с пробелами — для этого потребуются дополнительные методы
- Доступен только с Java 6 и выше
Для более сложных случаев, когда требуется проверить, содержит ли строка только пробелы, можно использовать комбинацию с методом trim():
if (str != null && str.trim().isEmpty()) {
// Строка пуста или содержит только пробельные символы
}
Начиная с Java 11, появился более удобный метод isBlank(), который делает именно это:
if (str != null && str.isBlank()) {
// Строка пуста или содержит только пробельные символы
}
Метод 3: Проверка через length() и длину строки
Альтернативный способ проверки строки на пустоту — использование метода length(), который возвращает количество символов в строке. Этот метод присутствует в Java с первых версий и активно используется для различных операций со строками.
Основной паттерн использования:
if (str != null && str.length() == 0) {
// Строка существует, но пуста
}
if (str != null && str.length() > 0) {
// Строка существует и не пуста
}
Важно помнить, что length() — это метод объекта String, а не свойство, поэтому требуются скобки. Это отличает его от массивов, где длина действительно является свойством (array.length без скобок).
С точки зрения производительности, использование length() и isEmpty() практически идентично. Фактически, isEmpty() в своей реализации просто проверяет, равна ли длина строки нулю:
public boolean isEmpty() {
return value.length == 0;
}
Выбор между length() и isEmpty() обычно основывается на читаемости кода и предпочтениях команды разработчиков.
- Используйте length(), когда вам также нужно знать конкретную длину строки или сравнивать её с другими значениями, а не только проверять на пустоту
- Используйте isEmpty() для более ясного выражения намерения проверить строку именно на пустоту
Метод length() также может быть полезен для более сложных условий:
// Проверка, что строка не null и имеет нужную длину
if (str != null && str.length() >= 5 && str.length() <= 10) {
// Строка имеет от 5 до 10 символов
}
// Проверка на короткие строки
if (str != null && str.length() < 3) {
// Строка слишком короткая
}
Метод 4: Надежные утилиты Objects.isNull() для Java-разработчиков
Начиная с Java 7, появился класс Objects, предоставляющий статические методы для операций с объектами, включая проверки на null. Этот класс предлагает более элегантный способ работы с потенциально пустыми ссылками.
Два основных метода для проверки на null:
// Проверка, что объект равен null
if (Objects.isNull(str)) {
// Строка null
}
// Проверка, что объект не равен null
if (Objects.nonNull(str)) {
// Строка не null
}
Хотя эти методы просто обертывают стандартные проверки (str == null и str != null соответственно), они повышают читаемость кода и обеспечивают единообразие проверок по всему приложению.
Для комплексной проверки строк на null и пустоту можно комбинировать эти методы с ранее рассмотренными:
if (Objects.nonNull(str) && !str.isEmpty()) {
// Строка не null и не пуста
}
Класс Objects также предлагает мощный метод requireNonNull(), который проверяет объект на null и выбрасывает исключение, если проверка не проходит:
// Проверка с выбросом стандартного исключения
String nonNullStr = Objects.requireNonNull(str);
// Проверка с пользовательским сообщением
String nonNullStr = Objects.requireNonNull(str, "Строка не должна быть null");
// Проверка с генерацией сообщения через лямбда (Java 8+)
String nonNullStr = Objects.requireNonNull(str,
() -> "Строка " + id + " не найдена в системе");
Этот метод особенно полезен для проверки параметров методов, когда null является недопустимым значением.
Преимущества использования класса Objects:
- Повышенная читаемость кода
- Унифицированный способ проверок по всему приложению
- Поддержка функциональных возможностей в новых версиях Java
- Совместимость с паттернами функционального программирования
Единственный недостаток — класс Objects доступен только с Java 7, поэтому не может использоваться в проектах, требующих совместимости с более ранними версиями Java.
Для полноценной проверки строк, с учетом всех возможных случаев, рекомендуется создать свой утилитный класс:
public class StringUtils {
public static boolean isNullOrEmpty(String str) {
return Objects.isNull(str) || str.isEmpty();
}
public static boolean isNullOrBlank(String str) {
return Objects.isNull(str) || str.trim().isEmpty();
}
public static boolean hasText(String str) {
return Objects.nonNull(str) && !str.trim().isEmpty();
}
}
Такой класс позволит значительно упростить проверки строк во всем приложении и сделать код более читаемым:
if (StringUtils.isNullOrEmpty(username)) {
throw new ValidationException("Имя пользователя не может быть пустым");
}
if (StringUtils.hasText(description)) {
saveDescription(description.trim());
}
Проверка строк на null и пустоту — это фундаментальный навык для Java-разработчика, который спасает от непредвиденных ошибок и повышает стабильность кода. Выбирайте подход, подходящий вашему проекту, учитывая требования к читаемости и производительности. Создайте набор утилитных методов, которые соответствуют стилю вашей команды, и последовательно используйте их во всей кодовой базе. Помните: лучшие разработчики не те, кто пишет сложный код, а те, кто предотвращает непредвиденные ситуации, задолго до того, как они могут возникнуть.