


Optional в Java явно сообщает, что результат может отсутствовать. Вместо вызова get с надеждой на наличие данных лучше описать, что сделать со значением и что вернуть или выбросить при его отсутствии. Это особенно полезно на границе поиска объекта и бизнес-логики.
В разборе Mentoring.digital используем методы, доступные в Java 8 и новее. Optional не устраняет все null в программе и не заменяет обработку ошибок выполнения.
import java.util.Optional;
public class OptionalDemo {
static Optional<String> cleanName(String raw) {
return Optional.ofNullable(raw)
.map(String::trim)
.filter(value -> !value.isEmpty());
}
static String fallback() {
System.out.println("Запасной вариант вычислен");
return "Гость";
}
public static void main(String[] args) {
String displayName = cleanName(" Анна ")
.orElseGet(OptionalDemo::fallback);
System.out.println(displayName);
String guest = cleanName(" ").orElse("Гость");
System.out.println(guest);
}
}
ofNullable превращает null в пустой Optional. map обрезает пробелы, если строка есть, а filter отбрасывает пустой результат. Для null, пустой строки и строки из пробелов теперь действует одно явно выбранное правило. Если по требованиям эти случаи различаются, объединять их нельзя.
В первом вызове fallback не запускается, потому что имя найдено. Программа печатает Анна, затем Гость. Проверьте отдельно null, пробелы и обычное имя. trim в этом упражнении не является универсальной нормализацией всех пробельных символов Unicode.
Аргумент метода вычисляется до вызова метода. Поэтому выражение optional.orElse(fallback()) запустит fallback даже при наличии значения. orElseGet принимает поставщика и вызывает его только для пустого Optional. Для готовой константы orElse вполне подходит; для вычисления или операции с побочным эффектом различие существенно.
Не используйте этот выбор как повод скрыть ошибку обращения к базе запасным результатом. Отсутствующая запись и недоступная база означают разные ситуации. Optional подходит для первого случая, а второй должен сохранить свою ошибку.
Если функция уже возвращает Optional, обычный map создаст вложенный контейнер Optional<Optional<T>>. flatMap позволяет продолжить цепочку без этого уровня. Сам переданный в flatMap метод не должен возвращать null.
static Optional<String> departmentEmail(String department) {
return "support".equals(department)
? Optional.of("help@example.test")
: Optional.empty();
}
// Внутри метода main:
Optional<String> email = cleanName(" support ")
.flatMap(OptionalDemo::departmentEmail);
String requiredEmail = email.orElseThrow(
() -> new IllegalArgumentException("Отдел без адреса")
);
Добавьте departmentEmail как статический метод OptionalDemo, а оставшуюся часть внутрь main. Адрес example.test здесь учебный, отправки сообщений нет. При неизвестном отделе orElseThrow выдаст выбранное исключение. При известном отделе вернётся строка.
Цепочки преобразований удобно отрабатывать на курсе Java с наставником. Если сомневаетесь в контракте метода, покажите вызывающий код ментору по Java, а не только отдельный Optional.