Использование Optional для безопасности при работе с null
На предыдущем этапе мы узнали, как предотвратить ошибку NullPointerException
, явно проверяя, является ли объект null
перед его использованием. Хотя этот подход эффективен, он иногда может привести к тому, что код будет перегружен проверками на null
. В Java 8 был введен класс Optional
как способ более функционального и выразительного управления потенциально null
значениями.
Optional
представляет собой контейнерный объект, который может содержать или не содержать не-null
значение. Если значение присутствует, метод isPresent()
возвращает true
, а метод get()
возвращает это значение. Если значение отсутствует, объект считается пустым, и метод isPresent()
возвращает false
. Вызов метода get()
для пустого объекта Optional
вызывает исключение NoSuchElementException
.
Давайте перепишем наш пример, чтобы использовать Optional<Character>
для обработки возможности null
значения для объекта Character
.
-
Откройте файл HelloJava.java
в редакторе WebIDE.
-
Замените все содержимое файла следующим кодом:
import java.util.Optional;
public class HelloJava {
public static void main(String[] args) {
Character myChar = null; // По-прежнему может быть null
// Создаем объект Optional из потенциально null объекта Character
Optional<Character> optionalChar = Optional.ofNullable(myChar);
// Используем методы Optional для проверки и обработки значения
if (optionalChar.isPresent() && Character.isLetter(optionalChar.get())) {
System.out.println("myChar is a letter.");
} else {
System.out.println("myChar is not a letter or is null.");
}
// Другой способ с использованием функциональных методов Optional (более продвинутый)
// optionalChar.filter(Character::isLetter)
// .ifPresentOrElse(
// c -> System.out.println("myChar is a letter (using Optional methods)."),
// () -> System.out.println("myChar is not a letter or is null (using Optional methods).")
// );
}
}
В этом коде:
- Мы импортируем класс
Optional
.
- По-прежнему объявляем
myChar
как потенциально null
.
Optional<Character> optionalChar = Optional.ofNullable(myChar);
создает объект Optional
. Метод Optional.ofNullable()
используется, когда значение может быть null
. Если myChar
равно null
, optionalChar
будет пустым объектом Optional
. Если myChar
имеет значение, optionalChar
будет содержать это значение.
- Затем мы используем метод
optionalChar.isPresent()
для проверки, содержит ли объект Optional
значение, прежде чем пытаться получить его с помощью optionalChar.get()
и передать в метод Character.isLetter()
. Это похоже на нашу предыдущую проверку на null
, но использует API класса Optional
.
- Закомментированная часть показывает более продвинутый способ использования
Optional
с функциональными методами, такими как filter
и ifPresentOrElse
, которые могут сделать код более компактным в определенных сценариях. В этом вводном уроке мы не будем фокусироваться на этом продвинутом использовании, но полезно знать о нем.
-
Сохраните файл.
-
Скомпилируйте программу:
javac HelloJava.java
-
Запустите программу:
java HelloJava
Вывод должен быть таким же, как на предыдущем этапе:
myChar is not a letter or is null.
Это подтверждает, что использование Optional.ofNullable()
и isPresent()
корректно обрабатывает случай null
.
Теперь изменим myChar
на не-null
символ, чтобы посмотреть, как ведет себя программа.
-
Измените файл HelloJava.java
, установив myChar
равным символу, например, 'A':
import java.util.Optional;
public class HelloJava {
public static void main(String[] args) {
Character myChar = 'A'; // Теперь myChar имеет значение
// Создаем объект Optional из потенциально null объекта Character
Optional<Character> optionalChar = Optional.ofNullable(myChar);
// Используем методы Optional для проверки и обработки значения
if (optionalChar.isPresent() && Character.isLetter(optionalChar.get())) {
System.out.println("myChar is a letter.");
} else {
System.out.println("myChar is not a letter or is null.");
}
}
}
-
Сохраните файл.
-
Скомпилируйте программу:
javac HelloJava.java
-
Запустите программу:
java HelloJava
На этот раз вывод должен быть следующим:
myChar is a letter.
Это показывает, что когда myChar
имеет значение, метод optionalChar.isPresent()
возвращает true
, и проверка Character.isLetter()
выполняется корректно.
Использование Optional
может сделать ваш код более читаемым и явно указать, когда значение может отсутствовать, уменьшая вероятность неожиданных ошибок NullPointerException
.