Добавление java.util.Optional  в Java получило радушный прием и обеспечило более плавный код для методов, которые иногда могут возвращать null значения. К сожалению, Optional часто злоупотребляли, в частности, его слишком часто использовали. Иногда я сталкивался с кодом, который использует Optional в случаях, когда нет явного преимущества перед непосредственным использованием null.

Если при вызове кода используется Optional.ofNullable(T) для возвращаемого значения из метода, который он только что вызвал, это может предупреждать, что использование Optional не дает никаких преимуществ перед обычной проверкой на null.

Как и в случае со всеми« красными флажками», это не означает, что передавать возвращаемое значение из метода в Optional.ofNullable(T) всегда плохо (фактически, это необходимо делать для API-интерфейсов, имеющим Optional параметр), но обычно этот подход используется, чтобы не предоставлять реального значения, вместо прямого использования возвращаемого значения и его проверки на null.

Далее показан код, используемый до того как был доступен Optional, для проверки того, что метод возвращает значение null и выполняющий одно действие для ответа null, и другой - в случае не null ответа (все фрагменты кода в этом сообщении доступны на GitHub).

/**
 * Демонстрирует подход к условным переходам на основе {@code null} или 
 * not {@code null}, что является традиционным подходом до {@ link Optional}.
 */
public void demonstrateWithoutOptional()
{
    final Object returnObject = methodPotentiallyReturningNull();
    if (returnObject == null)
    {
        out.println("Возвращенный объект равен null.");
    }
    else
    {
        out.println("Возвращенный объект НЕ равен null: " + returnObject);
        // код обработки возвращаемого non-null объекта помещен здесь ...
    }
}

Для такого простого условия редко требуется задействовать Optional. Следующий фрагмент кода представляет тип кода, который я иногда видел, когда разработчик пытается заменить явное определение значения null на использование Optional:

/ **
  * Демонстрирует использование {@link Optional} точно так же, как {@code null}
  * часто используется (зависит от того, является ли возвращаемое значение пустым или
  * нет в зависимости от того, является ли возвращаемое значение {@code null} или нет).
  * /
public void demonstrateOptionalUsedLikeNullUsed()
{
    final Optional<Object> optionalReturn
       = Optional.ofNullable(methodPotentiallyReturningNull());
    if (optionalReturn.isEmpty())
    {
        out.println("Возвращенный объект пуст.");
    }
    else
    {
        out.println("Возвращенный объект НЕ пуст: " + optionalReturn);
        // код обработки non-null возвращаемого объекта помещен здесь ...	
    }
}

Парадигма в этом коде по существу такая же, как и в традиционном коде проверки на null, но для выполнения той же проверки используется Optional.isEmpty(). Этот подход не добавляет удобочитаемости или других преимуществ, но требует небольших затрат на создание дополнительных объектов и вызов метода.

Вариантом вышеупомянутого использования Optional является использование его метода ifPresent(Consumer) в сочетании с его методом isEmpty() для формирования одной и той же базовой логики выполнения одного действия, если возвращаемое значение присутствует, и другого действия, если возвращаемое значение пусто. Это демонстрируется в следующем коде.

/ **
  * Демонстрирует использование {@link Optional} методов {@link Optional#ifPresent(Consumer)}
  * и {@link Optional#isEmpty()} аналогично традиционным условиям на основе проверок
  * на {@code null} или не {@code null}.
  * /
public void demonstrateOptionalIfPresentAndIsEmpty()
{
    final Optional<Object> optionalReturn
       = Optional.ofNullable(methodPotentiallyReturningNull());
    optionalReturn.ifPresent(
       (it) -> out.println("Возвращенный объект НЕ пуст: " + it));
    if (optionalReturn.isEmpty())
    {
        out.println("Возвращенный объект пуст.");
    }
}

Этот код выглядит немного короче, чем традиционный подход к непосредственной проверке возвращаемого значения null, но все же требует создания дополнительных экземпляров объекта и требует двух вызовов методов. Кроме того, кажется немного странным сначала проверить, присутствует ли Optional, а затем сразу же после этого проверить, пусто ли оно. Кроме того, если логика, которую необходимо было выполнить, была более сложной, чем вывод сообщения на стандартный вывод, этот подход становится менее удобным.

Заключение

Код, который обрабатывает возвращаемое значение метода и должен делать что-то одно, если возвращаемое значение равно, null и делать другое, если возвращаемое значение не равно null, редко будет пользоваться каким-либо преимуществом обертывания этого возвращаемого значения Optionalпросто для проверки того, присутствует оно или пусто. 

Обертывание возвращаемого значения метода в объект Optional, вероятно, оправдывает затраты только в том случае, если Optional используется в рамках плавного связывания или API-интерфейсов, которые работают с Optional.

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