что такое optional в java

Java Optional не такой уж очевидный

что такое optional в java. 248c56e97e95a0d4c963f5896455f928. что такое optional в java фото. что такое optional в java-248c56e97e95a0d4c963f5896455f928. картинка что такое optional в java. картинка 248c56e97e95a0d4c963f5896455f928. Optional обладает огромным количеством фичей, правильное использование которых позволяет добиться более простого и понятного кода.

Optional не должен равняться null

Знайте API

Optional обладает огромным количеством фичей, правильное использование которых позволяет добиться более простого и понятного кода.

Идея проста: если имя отсутствует, вернуть значение по умолчанию. Можно сделать это лучше.

Давайте рассмотрим что-нибудь посложнее. Предположим, что мы хотим вернуть Optional от имени пользователя. Если имя входит в список разрешенных, контейнер будет хранить значение, иначе — нет. Вот многословный пример.

Optional.filter упрощает код.

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

Отдавайте предпочтение контейнерам «на примитивах»

Не пренебрегайте ленивыми вычислениями

Optional.orElse — это удобной инструмент для получения значения по умолчанию. Но если его вычисление является дорогой операцией, это может повлечь за собой проблемы с быстродействием.

Даже если таблица присутствует в кэше, значение с удаленного сервера будет запрашиваться при каждом вызове метода. К счастью, есть простой способ избежать этого.

Optional.orElseGet принимает на вход лямбду, которая будет вычислена только в том случае, если метод был вызван на пустом контейнере.

Не оборачивайте коллекции в Optional

Хотя я и видел такое не часто, иногда это происходит.

Любая коллекция является контейнером сама по себе. Для того чтобы показать отсутствие элементов в ней, не требуется использовать дополнительные обертки.

Чрезмерное использование Optional усложняет работу с API.

Не передавайте Optional в качестве параметра

А сейчас мы начинаем обсуждать наиболее спорные моменты.

Во-вторых, applySettings обладает четырьмя потенциальными поведениями в зависимости от того, являются ли переданные Optional пустыми, или нет.

Optional главным образом предназначен для использования в качестве возвращаемого значения в тех случаях, когда нужно отразить состояние «нет результата» и где использование null может привести к ошибкам.

Optional буквально символизирует нечто, что может содержать значение, а может — нет. Передавать возможное отсутствие результата в качестве параметра звучит как плохая идея. Это значит, что API знает слишком много о контексте выполнения и принимает те решения, о которых не должен быть в курсе.

Что же, как мы можем улучшить этот код? Если age и role должны всегда присутствовать, мы можем легко избавиться от Optional и решать проблему отсутствующих значений на верхнем уровне.

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

С другой стороны, если значения age и role могут быть опущены, вышеописанный способ не заработает. В этом случае лучшим решением будет разделение API на отдельные методы, удовлетворяющим разным пользовательским потребностям.

Возможно это выглядит несколько многословно, но теперь пользователь может сам решить, какой метод вызвать, избегая непредвиденных ошибок.

Не используйте Optional в качестве полей класса

Я слышал разные мнения по этому вопросу. Некоторые считают, что хранение Optional напрямую в полях класса позволяет сократить NullPointerException на порядок. Мой друг, который работает в одном известном стартапе, говорит, что такой подход в их компании является утвержденным паттерном.

Хотя хранение Optional в полях класса и звучит как хорошая идея, я думаю, что это может принести больше проблем, чем пользы.

Отсутствие сериализуемости

На мой взгляд, этот аргумент является наименее убедительным, так как сейчас, в мире микросервисов и распределенных систем, платформенная сериализация не является настолько важной, как раньше.

Хранение лишних ссылок

Optional — это объект, который необходим пользователю всего несколько миллисекунд, после чего он может быть безболезненно удален сборщиком мусора. Но если мы храним Optional в качестве поля, он может оставаться там вплоть до самой остановки программы. Скорее всего, вы не заметите никаких проблем с производительностью на маленьких приложениях. Однако, если речь идет о большом сервисе с дюжинами бинов, последствия могут быть другие.

Плохая интеграция со Spring Data/Hibernate

Предположим, что мы хотим построить простое Spring Boot приложение. Нам нужно получить данные из таблицы в БД. Сделать это очень просто, объявив Hibernate сущность и соответствующий репозиторий.

Теперь все сломано.

Hibernate не может замапить значения из БД на Optional напрямую (по крайней мере, без кастомных конвертеров).

Но некоторые вещи работают правильно

Должен признать, что в конечном итоге не все так плохо. Некоторые фреймворки корректно интегрируют Optional в свою экосистему.

Jackson

Давайте объявим простой эндпойнт и DTO.

Как ни странно, все по-прежнему работает так, как и ожидается.

Это значит, что мы можем использовать Optional в качестве полей DTO и безопасно интегрироваться со Spring Web? Ну, вроде того. Однако есть потенциальные проблемы.

SpringDoc

SpringDoc — это библиотека для Spring Boot приложений, которая позволяет автоматически сгенерировать Open Api спецификацию.

Вот пример того, что мы получим для эндпойнта GET /person/ .

Это приведет к интересным результатам.

В чем здесь проблема? Например, если кто-то на фронтенде использует генератор типов сущностей по схеме Open Api, это приведет к получению неверной структуры, что в свою очередь может привести к повреждению данных.

Решение

Что же нам делать со всем этим? Ответ прост. Используйте Optional только для геттеров.

Однако у этого подхода есть один недостаток. Его нельзя полностью интегрировать с Lombok. Optional getters не подерживаются библиотекой и, судя по некоторым обсуждениям на Github, не будут.

На текущий момент единственным выходом является ручное объявление необходимых геттеров.

Источник

Новый класс Optional в Java 8, не панацея от NullPointerException

Итак, приступим к описанию основных возможностей этого нововведения.

Создание объектов Optional

Для начала приведу пример класса с использованием Optional :

Использование Optional для устранения избыточного кода

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

А теперь все то же самое, но с использованием Optional :

Намного лаконичнее, не правда ли?

Действия с объектом, с использованием метода ifPresent()

Метод ifPresent() позволяет также устранить некоторую избыточность кода, следующего вида:

Те же действия, но с использованием Optional :

Действия с объектом с использованием isPresent()

isPresent() не дает нам большой выгоды по устранению избыточности кода, но зато придает немного большую информативность написанному коду.

То же самое, но с использованием Optional :

Действия с объектом с использованием orElse(), orElseThrow()

И напоследок еще несколько методов для наведения «красоты» в коде.

То же самое, но с использованием Optional :

Или, если не хотим создавать объект, можно выбросить исключение:

Заключение

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

А также несомненно, Optional помогает придать большую информативность коду, повысить его читабельность.

На этом я завершу, свое короткое описания данного нововведения, спасибо за прочтение! Дополнительную информацию по этой теме Вы сможете найти по ссылкам, приведенным ниже.

Источник

Введение в Optional

что такое optional в java. duke. что такое optional в java фото. что такое optional в java-duke. картинка что такое optional в java. картинка duke. Optional обладает огромным количеством фичей, правильное использование которых позволяет добиться более простого и понятного кода.

В JDK 8 был введён новый утилитарный класс java.util.Optional, целями которого являются повышение null-safety и читаемости кода при работе со ссылками, значения которых могут быть null. Главная же цель Optional — замена null-значений, благодаря чему должна повышаться безопасность и читаемость кода.

Optional тесно связан с другими нововведениями JDK 8: Stream и лямбда-выражениями.

Пример использования

Допустим, у нас есть класс Employee, интерфейс EmployeeRepository для работы с источником данных и его реализация CachingEmployeeRepository, которая реализует кэширование и делегирует вызовы объекту другого реализующего класса.

В методе findOneById, идеальном для использования кэширования, общая последовательность действий выглядит следующим образом:

Примерно так будет выглядеть реализация метода findOneById без использования Optional:

А так будет выглядеть реализация этого же метода уже с использованием Optional:

Обратите внимание, что в коде отсутствуют проверки на null, что достигнуто благодаря Optional. Но тут есть два неудобных момента:

Первый неудобный момент решается использованием метода or вместо orElseGet, который был добавлен в JDK 9. С его применением, метод findOneById приобретёт следующий вид:

Пример OTN

В оригинальной статье на OTN, посвящённой Optional, в качестве примера приводилась следующая структура классов:

В результате чего абстрактная попытка получить версию USB установленной в компьютере звуковой карты будет выглядеть следующим образом:

Первый вариант может привести к NullPointerException, второй же исключает эту ситуацию, но требует большого количества кода для реализации достаточно простой задачи. Вариант с применением Optional будет выглядеть значительно проще:

Работа с Optional

Теперь, когда мы разобрали пару примеров использования Optional, можно разобраться с методами этого класса.

Методы создания

Объект типа Optional может быть создан тремя методами:

Методы преобразования

Непустой Optional может быть преобразован в другой Optional, который может содержать другое значение, значение другого типа или и вовсе быть пустым. Поскольку методы filter, map, flatMap и orвозвращают объекты типа Optional, можно создавать цепочки преобразований практически любой длины.

filter() — фильтрация значения

Методом filter значение Optional может быть «отфильтровано». В качестве аргумента метод принимает объект типа java.util.function.Predicate. Если значение удовлетворяет условиям фильтрации, то возвращён будет тот же Optional, в противном случае — пустой Optional.

map() и flatMap() — преобразование значения

Методом map из текущего Optional можно получить новый объект Optional, содержащий другое значение. В качестве аргумента метод принимает объект типа java.util.function.Function. Если переданная функция возвращает null, то метод map вернёт пустой Optional.

Метод flatMap работает аналогично, но он декларирует, что переданная функция должна возвращать другой Optional, пустой или содержащий новое значение.

В JDK 9 был добавлен метод or, позволяющий пустой Optional преобразовать в непустой. В качестве аргумента он принимает объект типа java.util.function.Supplier, метод get которого возвращает новый Optional и будет вызван только в том случае, если существующий Optional пустой.

Методы проверки

Единственным до JDK 11 методом проверки наличия значения был isPresent, который возвращает true, если объект Optional содержит значение, иначе — false.

В JDK 11 был добавлен метод-антипод isEmpty, возвращающий true, если значение отсутствует.

Методы получения значения

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

Метод get — простейший способ получения значения объекта Optional. Если Optional непустой, то он вернёт значение, иначе выбросит исключение NoSuchElementException. Поэтому при обращении к этому методу нужно либо проверять наличие значения при помощи Optional.isPresent(), либо использовать try/catch.

orElse()

Метод orElse возвращает значение объекта Optional или значение, переданное ему в качестве аргумента, которое может быть null.

orElseGet()

Метод orElseGet, в отличии от orElse принимает в качестве аргумента объект класса java.util.function.Supplier, который вернёт «запасное» значение, если объект Optional пустой. Таким образом, в отличии от метода orElse, метод orElseGet создаёт «запасное» значение только по необходимости, что немного правильнее с точки зрения использования ресурсов, особенно, когда получение значения умолчанию требует выполнения каких-либо блокирующих операций, например, обращения к базе данных.

orElseThrow()

Метод orElseThrow возвращает значение объекта Optional или выбрасывает исключение, возвращаемое объектом типа java.util.function.Supplier переданным ему в качестве аргумента.
В JDK 10 был добавлен orElseThrow без аргументов, выбрасывающий NoSuchElementException.

Условные методы

Условные методы ifPresent и ifPresentOrElse позволяют выполнить необходимое действие над значением объекта Optional, если оно задано.

ifPresent()

Метод ifPresent принимает в качестве аргумента объект типа java.util.function.Consumer, метод accept которого принимает текущее значение объекта Optional в качестве аргумента. Метод accept будет вызван только в том случае, если Optional содержит значение.

ifPresentOrElse()

Метод ifPresentOrElse аналогичен методу ifPresent, он был добавлен в JDK 9 и в качестве второго аргумента принимает объект типа java.lang.Runnable, метод run которого будет вызван, если объект Optional не содержит значения.

Прочие методы

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

Источник

Объект в футляре или Optional в Java 8 и Java 9. Часть 2: «Как это делается в Java 8»

что такое optional в java. . что такое optional в java фото. что такое optional в java-. картинка что такое optional в java. картинка . Optional обладает огромным количеством фичей, правильное использование которых позволяет добиться более простого и понятного кода.
Классу Optional посвящено немало статей и tutorials, в том числе этот и этот на Хабре.
Большинство из них рассказывают как вызываются методы этого класса. Я в этом tutorial делаю упор на то зачем, почему, в каких случаях можно (а скорее даже нужно) применять тот или иной метод класса. Я думаю, это очень важно, ибо как показал опрос после первой статьи этого tutorial, далеко не все Java — программисты вошли во вкус использования всей мощи методов этого класса.
Для лучшего объяснения методов класса я буду использовать более сложные и наглядные примеры, чем в большинстве других tutotials — кофеварку, фильтрационную установку, миксер и т.д.
Это вторая статья серии, посвящённая использованию класса Optional при обработке объектов с динамической структурой. В первой статье было рассказано о способах избежания NullPointerException в ситуациях, когда вы не можете или не хотите использовать Optional.
В этой статье мы рассмотрим все методы класса в том виде, как их предоставляет Java 8. Расширения класса в Java 9 рассмотрены в третьей статье этой серии. Четвертая статья посвящена необходимому (с точки зрения автора) дополнению к этому классу.
Ну а в пятой статье я рассказываю о том, где внутри класса следует применять Optional, подвожу итоги и дарю каждому читателю, дочитавшему серию до конца, ценный подарок.
В этом tutorial будет много исходного кода, в том числе и Junit тестов. Я разделяю мнение некоторых моих коллег по перу, что чтение тестового кода помогает лучшему усвоению материала. Все исходные тексты вы найдете в моём проекте на GitHub.
Итак, в первой статье этой серии я пытался рассмотреть подходы, которые вы можете использовать при реализации объектов с динамической структурой и пообещал обосновать, почему почти всегда Optional в этой ситуации работает лучше других подходов. Приступим к исполнению обещаний. Начнём с определения.

Что такое Optonal?

Перед тем как мы перейдем к рассмотрению конкретных пример, попытаемся ответить на вопрос, а что такое Optional?

Я рискну дать собственное наглядное определение. В первом приближении Optional — это программный аналог футляра физического объекта, например – очков. Лежит ли объект внутри футляра, вы можете узнать с помощью метода isPresent(). Если он там лежит, вы можете взять его с помощью метода get(). В общем, примерно так, как это показано на заглавной картинке серии.

В первом приближении Optional — это футляр для некоторого объекта.

Использование по-минимуму

В нашем первом примере мы пытаемся с использованием Java 8 Optional симулировать функционирование прибора, соединяющего в себе кран питьевой воды и кипятильник.
Его схема представлена на картинке внизу:

что такое optional в java. image loader. что такое optional в java фото. что такое optional в java-image loader. картинка что такое optional в java. картинка image loader. Optional обладает огромным количеством фичей, правильное использование которых позволяет добиться более простого и понятного кода.

Как можно видеть, для работы прибору нужна вода и электроэнергия. На выходе он может выдавать сырую или кипяченую воду.

Таким образом вход этого прибора можно описать таким вот интерфейсом:

Поскольку (в зависимости от входных данных) прибор может выдавать или не выдавать сырую и кипяченую воду, мы представляем результат вызова get… с помощью Optional.

Поведение прибора в целом описывает интерфейс, объединяющий методы входа и выхода.

Классы, представляющие разновидности воды для нас мало интересны, поэтому мы реализуем их минимальным образом. Вот это класс для порции сырой воды:

Мы будем считать, что порция кипяченной воды представляет собой новый, отличный от сырой воды объект. Поэтому мы представим его самостоятельным классом:

Итак, задача поставлена. В лучших традициях TDD (Test-Driven Development) пишем сначала тест для проверки, правильно ли мы симулировали поведение нашего простого прибора:

Наш тест проверяет, что прибор действительно выдает сырую воду если вода подается на вход, независимо от наличия электричества. А вот кипяченую воду прибор выдает только при наличии и воды и электричества.

Посмотрите мое, наверняка не оптимальное решение:

Обратите внимание на последнюю строчку листинга, где используется метод map() из класса Optional. Таким образом вы можете строить цепочки обработки. Если на одном из звеньев цепочки выяснится, что дальнейшая обработка невозможна, вся цепочка вернет пустой ответ.

Результаты нашей модели кипятильника зависят от внешних условий, которые задавались с помощью булевых переменных. Но в большинстве практически интересных задач на вход подаются не простые переменные, а объекты. В том числе такие, которые могут принимать значение null.

Рассмотрим, как можно применить Optional, если поведение определяется не булевыми переменными, а “старорежимными” объектами, допускающими нулевые значения.
Пусть вход нашего кипятильника несколько иной модели, чем в первом примере определяется следующим образом:

Нулевое значение объекта water означает, что вода в прибор из водопровода не поступает.
Тогда поведение прибора в целом задается следующим интерфейсом:

Как в предыдущем примере определяем тесты, проверяющие корректность нашей реализации:

А вот и сама реализация:

Как мы видим, метод Optional.ofNullable() позволяет элегантно “положить” в футляр опасный объект с потенциально нулевым значением. Если объект имеет нулевое значение, футляр будет пустой. В противном случае в нем лежит необходимый нам объект.

Пора подвести первые итоги и сформулировать первые правила, для минимального использования Optional:

Если ваш метод выдает объект, который может присутствовать, а может отсутствовать, вы «укладываете» его в Optional. При укладке вы используете следующие правила:

УсловиеИспользуемый метод класса
Объект отсутствуетOptional.empty()
Объект присутствует и точно не nullOptional.of(. )
Объект присутствует, но может быть nullOptional.ofNullable(. )

Находится ли объект в футляре, вы определяете с помощью метода isPresent(). И если проверка дала положительный результат, вы извлекаете объект из футляра с помощью get()

Вот мы и освоили использование Optional так, чтобы больше не использовать null в качестве возвращаемого результата.

Но не будем останавливаться на достигнутом.

Рассмотрим теперь другую, не такую уж редкую ситуацию, когда некий ресурс представлен основным и резервным элементом.

Хорошо, когда есть заначка.

В технических системах нередко ресурсы одного и того же вида могут быть доступны более чем одним способом.

В следующем примере мы рассмотрим простое приспособление подачи воды. Так устроены поливальные устройства, применяемые дачниками. В специальную емкость собирается дождевая вода, которая и расходуется затем в первую очередь. Если же её нет или она кончилась, расходуется вода из водопровода.

Мы не будем усложнять задачу излишними деталями о неполной заполненности дождевого бака и его размере и просто используем снова знакомый уже класс CupOfWater.

Вход такого приспособления описывается таким образом:

Если дождевая вода не собрана, то на входе мы имеем нулевой объект, иначе – нормальный объект.

Выход прибора описывается следующим интерфейсом:

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

Поведение прибора в целом определяется совокупностью этих интерфейсов:

Как и в предыдущих примерах, подготовим вначале тесты для проверки поведения нашей реализации:

Наши ожидания таковы: прибор выдает воду независимо от того, заполнен бак с дождевой водой или нет, поскольку в последнем случае вода возьмется из “резерва” (водопровода).

Рассмотрим теперь реализацию:

Как мы видим, в сцепку к методу ofNullable() добавился метод orElse. Если первый элемент выдаст пустой Optional (дождевой воды не накоплено) второй метод добавит от себя объект. Если же первый метод выдаст непустой Optional, второй метод просто пропустит его через себя и водопроводная вода останется нетронутой.

Эта реализация предполагала наличие резервного объекта. Если же объект перед этим необходимо создать (в нашем случае – накачать воду) можно использовать метод orElseGet() с параметром типа Supplier:

Не выпускаем джина из бутылки

В некоторых случаях ограничения на ваш API не позволяет использовать Optional в качестве возвращаемого значения.

Предположим, что наш интерфейс определен таким образом, что клиент всегда ожидает на выходе нашей функции некоторый объект. Если запрашиваемого ресурса на момент запроса нет, и мы не хотим возвращать null, нам остается одно средство – выбросить Exception. Тем самым мы не выпускаем джина из бутылки – не даем возможности выпущенному нулевому объекту обернутся уже в коде клиента NullPoiner Exception.

Может ли нам помочь в этом случае Java 8 Optional? Да, может.
Но перед тем, как рассмотреть решение, подготовим тест, проверяющий корректность его работы:

Думаю, многих читателей это решение не очень убедит. В самом деле, чем это лучше проверки на null с помощью if?

Основным аргументом в пользу этого решения является возможность строить таким образом цепочки функциональных вызовов. Однако цепочка может прерваться выбросом Exception. В четвертой статье этого цикла я рискну предложить своё решение проблемы обработки Exception в подобных цепочках функциональных вызовов.

Пришла пора сформулировать новую группу правил по использованию Optional для случая, когда у нас есть несколько альтернатив для создания динамического объекта:

Если у ваш есть две и больше альтернатив для создания динамического объекта, используйте следующие правила::

УсловиеИспользуемый метод класса
Альтернативный объект присутствуетorElse(. )
Альтернативный объект надо сначала создать (например, достать из repository)orElseGet(()->. )
Альтернативный ресурс иссяк (бросаем exception)orElseThrow(()->new IllegalStateException(. ))

До сих пор мы рассматривали использование Optional на этапах создания и простого использования объектов с динамической структурой. Рассмотрим теперь вопрос, как Optional может нам помочь при трансформациях таких объектов.

Использование Optional в преобразователях

Преобразователь (Transformer) получает на вход некий объект и либо его изменяет либо преобразует в некий другой объект. В нашем случае, поскольку мы ограничиваемся использованием Optional, в качестве объекта на входе мы имеем всегда Optional. Напомним, что это можно себе представить как футляр или контейнер, в котором находится или не находится объект.

Преобразовать его можно либо в “настоящий” объект какого-либо типа, либо в новый футляр с каким-либо новым объектом.

На абстрактном уровне все варианты такого преобразования можно выразить в виде трех формул, приведенных внизу:

T t = f1(Optional opt)

U u = f2(Optional opt)

Optional = f3(Optional opt)

Кандидаты на роли функций преобразований f1, f2 и f3 – методы из класса Optional представлены в этой таблице:

Кандидаты на роль f1Кандидаты на роль f2Кандидаты на роль f3
filter()map()flatMap()
orElse()
map()orElseGet()

В предыдущих постах этого цикла мы уже рассмотрели большинство из этих методов. Нерассмотренными остались только filter и flatMap.

Ниже мы рассмотрим примеры использования этих методов.

Фильтрование (использование метода filter)

В следующем примере мы рассмотрим использование метода filter() который возвращает объект только если футляр не пуст и содержащийся в нем объект удовлетворяет некоторому критерию.
В нашем случае в качестве объекта мы будем использовать порцию воды в емкости для сбора полива дачного участка. Не вдаваясь в разбор физических и химических особенностей, будем считать, что собранная вода может быть либо чистой (удовлетворять критерию) либо нет.
Максимально упрощенная схема прибора показана на рисунке внизу.

что такое optional в java. image loader. что такое optional в java фото. что такое optional в java-image loader. картинка что такое optional в java. картинка image loader. Optional обладает огромным количеством фичей, правильное использование которых позволяет добиться более простого и понятного кода.

Поведение нашего прибора мы упростим максимально, сведя все к вопросу: выдается ли порция воды в том или ином случае или нет. После этого упрощения семантику поведения прибора можно описать этой таблицей:

что такое optional в java. image loader. что такое optional в java фото. что такое optional в java-image loader. картинка что такое optional в java. картинка image loader. Optional обладает огромным количеством фичей, правильное использование которых позволяет добиться более простого и понятного кода.

Полностью коды этого примера вы можете найти в упомянутом в начале статьи проекте на GitHuB в package eu.sirotin.example.optional4

Вначале познакомимся с классом представляющим собранную дождевую воду:

Как вы можете видеть, с помощью метода isClean() можно узнать, является ли собранная вода чистой или нет.

Этот класс используется в качестве входного параметра в нашем приборе.
Этот же объект но в “футляре” используется на выходе прибора.

А полностью поведение прибора описывается составным интерфейсом:

И опять подготовим вначале тест для проверки корректности моделирования поведения нашего прибора. Нетрудно видеть, что ожидания в тестах внизу полностью соответствуют таблице поведения представленной вверху.

Ну а теперь приступим к рассмотрению реализации нашего класса с помощью Optional.
Вот его полный текст:

В последней строчке показано использование метода filter(). В качестве критерия используется значение возвращаемое методом объекта isClean().

Обратите внимание также на использование методов ofNullable() и filter() в цепочке вызовов. Неправда ли, выглядит очень элегантно?

Трансформация – (использование метода flatMap)

Предположим, что рассмотренный в прошлом примере прибор заменен на другой, способный очищать загрязненную дождевую воду.

Его максимально упрощенная схема показана внизу.

что такое optional в java. image loader. что такое optional в java фото. что такое optional в java-image loader. картинка что такое optional в java. картинка image loader. Optional обладает огромным количеством фичей, правильное использование которых позволяет добиться более простого и понятного кода.

А поведение прибора описывается вот такой семантической таблицей:

что такое optional в java. image loader. что такое optional в java фото. что такое optional в java-image loader. картинка что такое optional в java. картинка image loader. Optional обладает огромным количеством фичей, правильное использование которых позволяет добиться более простого и понятного кода.

Если мы сравним эту и предыдущую таблицы, то увидим очевидное преимущество нового прибора: он выдает чистую воду даже в случае, если на вход поступила загрязненная дождевая вода.
Как всегда, начнем с интерфейсов описывающих вход и выход прибора:

Подготовим тест, проверяющий, реализует прибор ли ожидаемое от него поведение:

Ну а теперь рассмотрим и сам класс:

Использование метода flatMap() показано в последней строчке. В отличие от метода map() этот метод возвращает не сам объект а футляр (контейнер), который может быть и пустой.

Использование Optional в потребителях объектов (Consume)

В первом примере мы рассмотрели использование метода isPresent(), позволяющего определить, находится ли объект в футляре. В случае, если дальнейшая обработка предполагается только в случае его наличия, вместо isPresent(. ) целесообразнее использовать ifPresent(. )

Этот метод не возвращает какого-либо значения, но позволяет обработать объект в футляре, если он там присутствует. Если его там нет, ничего не происходит.

Рассмотрим его действие на примере еще одного прибора, который является усложнением предыдущего за счет дополнительной функции. Новый вариант прибора может не только очищать дождевую воду от загрязнений, но и смешивать её с некими добавками. Как и в предыдущих примерах, нас не будут интересовать детали об этих добавках.

Схема прибора показана на рисунке внизу:

что такое optional в java. image loader. что такое optional в java фото. что такое optional в java-image loader. картинка что такое optional в java. картинка image loader. Optional обладает огромным количеством фичей, правильное использование которых позволяет добиться более простого и понятного кода.

Вначале определим новый класс, представляющий результат смешивания:

Выход прибора определяется вот этим интерфейсом:

В качестве входа мы используем интерфейс из предыдущего примера. Тогда полностью вход и выход прибора определяется таким совместным интерфейсом:

Поведение прибора сходно с поведением предыдущего прибора, только вместо очищенной дождевой воды мы получаем очищенную дождевую воду с желаемыми добавками.

Составим тест для проверки корректности поведения нашего прибора:

А вот и реализация основного класса:

Посмотрим внимательнее на использование метода ifPresent(). Как мы видим, в качестве входного параметра метода используется метод из нашего же класса mix(). Он в свою очередь ожидает в качестве входного параметра объект типа CupOfWater. Заметьте, что футляр с объектом именно этого типа возвращает метод getCleanedWater().

Сформулируем правила использования Optional в потребителях (клиентах).

Если обработка потенциально пустого объекта будет производиться только в положителином случае (объект не пустой) — используйте метод IfPresent(. )
В противном случае, вы можете узнать, лежит ли объект внутри футляра с помощью метода isPresent(). Если он там лежит, вы можете взять его с помощью метода get().

Ну вот и все примеры, которые я хотел рассмотреть применительно к классу Optional в Java 8.

Но наш разговор об этом классе еще не закончен. В следующих статьях я расскажу о нововведениях в этом классе в Java 9, а также о некоторых его недостатках и ограничениях.
Переход к третьей статье этой серии.
Иллюстрация: ThePixelman

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *