0 added
0 removed
Original
2026-01-01
Modified
2026-03-10
1
<p>Теги: java, java developer, программирование на java, разработка на java, null-монада</p>
1
<p>Теги: java, java developer, программирование на java, разработка на java, null-монада</p>
2
<p>В программировании часто возникает задача вернуть из функции какое-нибудь значение. Причём это значение может быть, а может и не быть. Например, функция обращается к таблице базы данных и выбирает некоторое значение по ключу. Это значение может найтись, а может и не найтись.</p>
2
<p>В программировании часто возникает задача вернуть из функции какое-нибудь значение. Причём это значение может быть, а может и не быть. Например, функция обращается к таблице базы данных и выбирает некоторое значение по ключу. Это значение может найтись, а может и не найтись.</p>
3
<p>Что делать со значением понятно - его надо просто вернуть. А что делать, если значения в таблице нет?</p>
3
<p>Что делать со значением понятно - его надо просто вернуть. А что делать, если значения в таблице нет?</p>
4
<h2>Рассмотрим варианты действий</h2>
4
<h2>Рассмотрим варианты действий</h2>
5
<p>Итак, у нас есть несколько вариантов:</p>
5
<p>Итак, у нас есть несколько вариантов:</p>
6
<p>Можно устанавливать специальный код ошибки, а потом его проверять. Такой подход широко практиковался в языке Си. Понятно, что сейчас это выглядит более чем странно.</p>
6
<p>Можно устанавливать специальный код ошибки, а потом его проверять. Такой подход широко практиковался в языке Си. Понятно, что сейчас это выглядит более чем странно.</p>
7
<p>Другой вариант - выбрасывать исключение типа VALUE_NOT_FOUND. Вариант популярный, но тоже с кучей недостатков. Начнём с типа исключения. Оно должно быть<strong>checked</strong>? Тогда его надо будет декларировать и дальше за собой таскать, сейчас это как минимум не модно. Если<strong>Unchecked</strong>, то как сообщить клиентскому коду, что может быть такие исключение и это фактически часть бизнес-логики?</p>
7
<p>Другой вариант - выбрасывать исключение типа VALUE_NOT_FOUND. Вариант популярный, но тоже с кучей недостатков. Начнём с типа исключения. Оно должно быть<strong>checked</strong>? Тогда его надо будет декларировать и дальше за собой таскать, сейчас это как минимум не модно. Если<strong>Unchecked</strong>, то как сообщить клиентскому коду, что может быть такие исключение и это фактически часть бизнес-логики?</p>
8
<p>Реализовывать бизнес-логику на исключениях тоже вариант ниже среднего. Поэтому, часто в таких случаях, если значение не найдено, возвращают просто<strong>null</strong>. Казалось бы, это годное решение. Однако работа с<strong>null-ами</strong>- так себе удовольствие. Надо постоянно думать про NullPointerException. Все решения какие-то несуразные.</p>
8
<p>Реализовывать бизнес-логику на исключениях тоже вариант ниже среднего. Поэтому, часто в таких случаях, если значение не найдено, возвращают просто<strong>null</strong>. Казалось бы, это годное решение. Однако работа с<strong>null-ами</strong>- так себе удовольствие. Надо постоянно думать про NullPointerException. Все решения какие-то несуразные.</p>
9
<h2>Какие есть ещё варианты?</h2>
9
<h2>Какие есть ещё варианты?</h2>
10
<p>В ряде языков программирования эта проблема решается при помощи так называемой<strong>Null-монады</strong>. Есть такая возможность и в<strong>java</strong>. Давайте с ней познакомимся.</p>
10
<p>В ряде языков программирования эта проблема решается при помощи так называемой<strong>Null-монады</strong>. Есть такая возможность и в<strong>java</strong>. Давайте с ней познакомимся.</p>
11
<p>Допустим, у нас есть функция, которая может возвращать или строку или<strong>Null</strong>:</p>
11
<p>Допустим, у нас есть функция, которая может возвращать или строку или<strong>Null</strong>:</p>
12
public String mayBeNull() { //return "test"; return null; }<p>Раскомментируйте нужную строку, чтобы получить нужный вариант.</p>
12
public String mayBeNull() { //return "test"; return null; }<p>Раскомментируйте нужную строку, чтобы получить нужный вариант.</p>
13
<h2>Как может выглядеть код, в котором будет использоваться эта функция?</h2>
13
<h2>Как может выглядеть код, в котором будет использоваться эта функция?</h2>
14
<p>Примерно так:</p>
14
<p>Примерно так:</p>
15
public void useMayBeNull() { String value = mayBeNull(); if (value == null) { System.out.println("action with null"); } else { System.out.println("action with NOT null: " + value); } }<p>В принципе, получился нормальный, рабочий вариант, который часто встречается на практике. Выглядит он громоздко, некрасиво. Более того, если вместо System.out.println мы захотим передавать значение в другие функции, то нам надо будет всегда помнить про возможность null, т. е. всегда делать проверку типа if (value == null), это очень неудобно и легко забыть.</p>
15
public void useMayBeNull() { String value = mayBeNull(); if (value == null) { System.out.println("action with null"); } else { System.out.println("action with NOT null: " + value); } }<p>В принципе, получился нормальный, рабочий вариант, который часто встречается на практике. Выглядит он громоздко, некрасиво. Более того, если вместо System.out.println мы захотим передавать значение в другие функции, то нам надо будет всегда помнить про возможность null, т. е. всегда делать проверку типа if (value == null), это очень неудобно и легко забыть.</p>
16
<p>Давайте перепишем этот пример с использованием<strong>null-монады</strong>. В java эта концепция реализуется через класс<strong>Optional</strong>.</p>
16
<p>Давайте перепишем этот пример с использованием<strong>null-монады</strong>. В java эта концепция реализуется через класс<strong>Optional</strong>.</p>
17
public Optional<String> mayBeNullOptional() { return Optional.ofNullable("test"); //return Optional.ofNullable(null); //return Optional.empty(); }<p>И как с этим работать:</p>
17
public Optional<String> mayBeNullOptional() { return Optional.ofNullable("test"); //return Optional.ofNullable(null); //return Optional.empty(); }<p>И как с этим работать:</p>
18
public void useMayBeNullOptional() { Optional<String> value = mayBeNullOptional(); System.out.println( value.map(val -> "action with NOT null:" + val) .orElse("action with null")); }<p>Обратите внимание, что в этом случае у нас нет<strong>if-условия</strong>. Т. е. у нас нет шанса забыть про обработку значений и неожиданно получить<strong>NPE-исключение</strong>. Да и сама запись получилась более компактная, красивая и современная.</p>
18
public void useMayBeNullOptional() { Optional<String> value = mayBeNullOptional(); System.out.println( value.map(val -> "action with NOT null:" + val) .orElse("action with null")); }<p>Обратите внимание, что в этом случае у нас нет<strong>if-условия</strong>. Т. е. у нас нет шанса забыть про обработку значений и неожиданно получить<strong>NPE-исключение</strong>. Да и сама запись получилась более компактная, красивая и современная.</p>
19
<p><em>В<a>следующей части</a>мы посмотрим на некоторые моменты использования<strong>Optional</strong>!</em></p>
19
<p><em>В<a>следующей части</a>мы посмотрим на некоторые моменты использования<strong>Optional</strong>!</em></p>
20
20