Optional в Java 8

В Java 8 есть полезный класс java.util.Optional. Он используется для избавления от большого числа проверок значений на null, которые затрудняют чтение кода.

Пусть, например, у нас есть класс:

Пример кода с экземпляром этого класса и проверкой на null:

Аналогичный код с использованием модного класса Optional:

Как видно из этого примера, код метода testMethodWithOptional стал короче на две строки. Если бы в исходном примере было бы ещё больше проверок на null, то сокращение размера кода было бы ещё больше заметно.

Давайте теперь разберёмся, что же у нас тут происходит. Сначала обратите внимание на вызов Optional.ofNullable(myClass). Этот вызов статического метода создаёт экземпляр класса Optional. Созданный экземпляр выступает в качестве контейнера, который может содержать, либо может не содержать не null  значение. Для проверки того, содержит ли контейнер значение, нужно использовать метод isPresent(), который возвращает true, если контейнер содержит значение. В примере выше мы его не использовали, но метод весьма полезен.

В дальнейшем вся работа происходит через методы этого контейнера. Метод ifPresent позволяет вызвать какой-либо код, использующий объект из контейнера, но этот код будет выполняться только в том случае, если контейнер содержит значение. В данном случае мы передаём туда ссылку на метод myMethod.

Если же нам нужно вызвать какой-то код, результатом которого нам нужно воспользоваться в дальнейшем, то нам нужно использовать метод map, который возвращает экземпляр Optional, содержащий возвращённое значение, если оно НЕ null. В примере выше внутри метода map мы вызываем наш метод getSomeValue у класса MyClass.

Но из нашего метода testMethodWithOptional нам нужно вернуть не сам контейнер, а хранящееся в нём значение или null, если значения нет. Для этого мы вызываем метод orElse, который возвращает хранящееся в контейнере Optional значение, если оно есть, либо значение, которое мы передадим в качестве аргумента метода. В данном случае в качестве аргумента мы передаём null.

Сокращение размера кода и проверок на null становится очень сильно заметно, если нам нужно подряд вызвать сначала один метода объекта, затем если вернулось НЕ null, то вызвать другой метод над возвращённым объектом и т. д. Пример:

Попробуйте поиграться с кодом выше. Например, попробуйте поправить код класса C или B, чтобы они возвращали null, тогда вы увидите, что экземпляр класса D  будет содержать строку "from orElse" , так как он создан в методе orElse, где ему в конструктор передалось именно это значение. В текущем же варианте кода экземпляр класса D будет содержать строку "from C".

Если метод вашего класса уже возвращает экземпляр Optional, то использование метода map приведёт к тому, что в результирующем значении будет Optional внутри Optional. Для того чтобы это избежать, используйте метод flatMap:

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

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

И вообще, я что-то отстал от жизни. Пора уже начинать что-нибудь писать про нововведения в Java 9, а я тут про старьё какое-то пишу.


Поделиться:

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

Ваш e-mail не будет опубликован.

*