Статьи

Java 8 Optional не только для замены нулевого значения

обзор

В Java 8 вы можете вернуть Optional вместо return null; как вы могли бы это сделать в Java 7. Это может иметь или не иметь большого значения в зависимости от того, стремитесь ли вы забыть проверить нулевое значение или используете ли вы статический анализ кода для проверки нулевых ссылок.

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

Простой дополнительный вариант использования

В старые времена Java 7 вы писали что-то вроде:

1
2
String text = something();
if (text != null) {

Примечание: Oracle Java 7 будет «Конец публичных обновлений» в апреле 2015 года.

Вместо этого вы можете написать:

1
2
3
Optional text = something();
if (text.isPresent()) {
    String text2 = text.get();

Однако, если вы параноик, вы можете написать.

1
2
3
Optional text = something();
if (text != null && text.isPresent()) {
    String text2 = text.get();

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

Более сложный пример

Давайте вместо этого рассмотрим этот пример

1
2
3
4
5
6
7
8
9
static String getFirstSecondThird(Nested nested) {
    try {
          return ((Contained2) nested.first.second).get(0).third;
    } catch (NullPointerException |
             ClassCastException |
             IndexOutOfBoundsException ignored) {
          return null;
    }
}

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

Необязательно позволяет обрабатывать все возможные состояния ошибки без исключений или вложенной логики if / else.

01
02
03
04
05
06
07
08
09
10
11
static Optional getFirstSecondThird(Optional nested) {
    return nested // could be non-present
            .map(x -> x.first) // could be null
            .map(x -> x.second) // could be null
            // could be another type
            .map(x -> x instanceof Contained2 ? (Contained2) x : null)
            .map(x -> x.list) // could be null
            .filter(x -> !x.isEmpty()) // could be empty
            .map(x -> x.get(0)) // could be null
            .map(x -> x.third); // could be null.
}

Мы получаем серию отображений и фильтров, которые прогрессируют, только если значение не равно нулю и присутствует. Если какое-либо значение равно нулю или фильтр не соответствует действительности, весь результат «отсутствует».

Вывод

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

дополнительный

Для вашего интереса, вот классы, которые я использовал в приведенном выше примере.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
static class Nested {
    Contained first;
}
 
static class Contained {
    IContained2 second;
}
 
interface IContained2 {
}
 
static class Contained2 implements IContained2 {
    List list;
}
 
static class Data {
    String third;
}
Ссылка: Java 8 Optional не только для замены нулевого значения от нашего партнера JCG Питера Лоури из блога Vanilla Java .