Возьмите два примера кода:
if(optional.isPresent()) {
//do your thing
}
if(variable != null) {
//do your thing
}
Насколько я могу судить, самое очевидное отличие состоит в том, что Optional требует создания дополнительного объекта.
Тем не менее, многие люди начали быстро принимать дополнительные. В чем преимущество использования опций по сравнению с нулевой проверкой?
if
утверждения оооочень последнее десятилетие, и теперь все используют монадные абстракции и лямбды.if(x.isPresent) fails_on_null(x.get)
вы выходите из системы типов и должны гарантировать, что код не сломается «в вашей голове» на (по общему признанию) коротком расстоянии между условием и вызовом функции. Вoptional.ifPresent(fails_on_null)
системе типов это гарантия для вас, и вам не о чем беспокоиться.Optional.ifPresent
(и различных других конструкций Java) является то, что вы можете эффективно изменять только конечные переменные и не можете генерировать проверенные исключения. ЭтогоifPresent
, к сожалению, достаточно, чтобы часто избегать .Ответы:
Optional
использует систему типов для выполнения работы, которую в противном случае вам пришлось бы делать в своей голове: помня, может ли быть указанная ссылкаnull
. Это хорошо. Всегда разумно позволить компилятору справляться с скучной рутинной работой и резервировать человеческую мысль для творческой, интересной работы.Без
Optional
этого каждая ссылка в вашем коде похожа на неразорвавшуюся бомбу. Доступ к нему может сделать что-то полезное, иначе он может завершить вашу программу с исключением.С опциональным и без
null
, каждый доступ к нормальной ссылке успешен, и каждая ссылка на опциональную успешно, если она не установлена, и вы не проверили это. Это огромная победа в ремонтопригодности.К сожалению, большинство языков, которые сейчас предлагаются
Optional
, не упраздненыnull
, поэтому вы можете извлечь выгоду только из концепции, введя строгую политику «абсолютно нетnull
, никогда». Поэтому,Optional
например, Java не так убедительна, как в идеале.источник
Optional
только для напоминания о том, что значение может быть нулевымПриводит
Optional
более сильную типизацию к операциям, которые могут потерпеть неудачу, как уже упоминалось в других ответах, но это далеко не самое интересное или ценное, что можноOptionals
найти на столе. Гораздо более полезной является возможность откладывать или избегать проверки на сбой, а также легко составлять множество операций, которые могут дать сбой.Подумайте, есть ли у вас
optional
переменная из вашего примера кода, тогда вам придется выполнить два дополнительных шага, каждый из которых может потенциально потерпеть неудачу. Если какой-либо шаг на этом пути не пройден, вы хотите вернуть значение по умолчанию. ИспользуяOptionals
правильно, вы получите что-то вроде этого:С
null
мне пришлось бы проверить трижды ,null
прежде чем продолжить, что добавляет много сложности и техническое обслуживание головных болей к коду.Optionals
есть этот чек , встроенный вflatMap
иorElse
функции.Заметьте, я не звонил ни
isPresent
разу, что вы должны воспринимать как запах кода при использованииOptionals
. Это не обязательно означает, что вы никогда не должны использоватьisPresent
, просто вы должны тщательно изучить любой код, который делает, чтобы увидеть, есть ли лучший способ. В противном случае, вы правы, вы получаете только минимальную выгоду безопасности по сравнению с использованиемnull
.Также обратите внимание, что я не так беспокоюсь о том, чтобы заключить все это в одну функцию, чтобы защитить другие части моего кода от нулевых указателей от промежуточных результатов.
.orElse(defaultValue)
Например, если имеет смысл использовать my в другой функции, у меня гораздо меньше проблем с ее размещением, и гораздо проще составлять операции между различными функциями по мере необходимости.источник
Это подчеркивает возможность нулевого значения в качестве действительного ответа, который люди часто предполагают (правильно или неправильно) не будет возвращен. Выделение тех немногих случаев, когда null действителен, позволяет исключить засорение вашего кода огромным количеством бессмысленных нулевых проверок.
В идеале установка переменной в null была бы ошибкой времени компиляции где угодно, но не обязательно; устранение исключений нулевого указателя во время выполнения. Очевидно, что обратная совместимость исключает это, к сожалению
источник
Позволь мне привести пример:
Совершенно ясно, для чего предназначен этот метод. Но что произойдет, если в хранилище нет пользователя с указанным идентификатором? Может выдать исключение или, может быть, он возвращает ноль?
Второй пример:
Теперь, что здесь происходит, если нет пользователя с данным идентификатором? Правильно, вы получаете экземпляр Optional.absent () и можете проверить его с помощью Optional.isPresent (). Подпись метода с помощью Optional более подробно описывает его контракт. Сразу понятно, как должен вести себя метод.
Это также имеет преимущество при чтении клиентского кода:
Я натренировал свой глаз, чтобы увидеть .get () как непосредственный запах кода. Это означает, что клиент намеренно игнорирует контракт вызванного метода. Это гораздо легче увидеть, чем без Optional, потому что в этом случае вы не сразу понимаете, что такое контракт вызываемого метода (допускает ли он нулевое значение или нет при возврате), поэтому вам нужно сначала проверить его.
Необязательный используется с соглашением о том, что методы с возвращаемым типом Необязательный никогда не возвращает нуль, и обычно также с (менее строгим) соглашением, что метод без необязательного возвращаемого типа никогда не возвращает ноль (но лучше аннотировать его с помощью @Nonnull, @NotNull или аналогичных) ,
источник
An
Optional<T>
позволяет вам иметь «отказ» или «отсутствие результата» в качестве допустимого значения ответа / возврата для ваших методов (подумайте, например, о поиске в базе данных). ИспользованиеOptional
вместо того,null
чтобы указывать сбой / отсутствие результата, имеет некоторые преимущества:null
может ли быть возвращен.null
, по крайней мере, на мой взгляд, не должно использоваться для обозначения чего-либо, поскольку семантика может быть не совсем понятной. Он должен использоваться, чтобы сообщить сборщику мусора, что ранее упомянутый объект может быть собран.Optional
Класс предоставляет множество методов приятно условно работу со значениями (например,ifPresent()
) или определить значения по умолчанию прозрачным образом (orElse()
).К сожалению, это не полностью устраняет необходимость
null
проверок в коде, поскольку самOptional
объект все еще может бытьnull
.источник
В дополнение к другим ответам, другое важное преимущество Optionals в написании чистого кода состоит в том, что вы можете использовать лямбда-выражение в случае наличия значения, как показано ниже:
источник
Рассмотрим следующий метод:
Теперь давайте посмотрим на код вызова:
Это может привести к потенциально трудным для отслеживания сбоям в другом месте, потому что
dance
не ожидал нулевого значения.Это вызывает ошибку компиляции, потому что танец ожидал
Person
неOptional<Person>
Если у меня не было человека, это вызывает исключение в этой строке, когда я незаконно пытался преобразовать
Optional<Person>
человека. Ключ в том, что в отличие от пропуска нулевого значения, кроме следов здесь, а не какого-то другого места в программе.Чтобы сложить все вместе: неправильное использование опционального облегчает отслеживание проблем, неправильное использование нулевого вызывает трудное отслеживание проблем.
источник
Optional.get()
плохо написанного кода - вы почти никогда не должны вызывать Optional.get без предварительной проверкиOptional.isPresent()
(как указано в OP), иначе вы можете написатьoptionalPersion.ifPresent(myObj::dance)
.В Objective-C все ссылки на объекты являются необязательными. Из-за этого код, который вы опубликовали, глупый.
Код, подобный приведенному выше, не слышен в Objective-C. Вместо этого программист просто:
Если
variable
содержит значение, тоdoThing
будет вызываться по нему. Если нет, никакого вреда. Программа будет рассматривать его как неактивный и продолжит работу.Это реальная выгода опционов. Вам не нужно засорять свой код
if (obj != nil)
.источник
Очевидная проблема здесь состоит в том , что если « по желанию» на самом деле является отсутствует (т.е. равно нулю) , то ваш код будет взрывать с NullReferenceException (или аналогичный) пытается вызвать любой метод на объектную ссылку нулевой!
Возможно, вы захотите написать статический метод класса Helper, который определяет нулевое значение для любого данного типа объекта, что-то вроде этого:
или, может быть, более полезно:
Но являются ли какие-либо из них действительно более читаемыми / понятными / поддерживаемыми, чем оригинал?
источник