5 ответов:
конечно, люди будут делать то, что они хотят. Но у нас было четкое намерение при добавлении этой функции, и это было не чтобы быть общей целью, возможно, типа, столько, сколько многие люди хотели бы, чтобы мы сделали это. Наше намерение состояло в том, чтобы обеспечить ограниченный механизм для типов возврата библиотечных методов, где должен быть четкий способ представления "нет результата" и использование
nullибо такое было в подавляющем большинстве случаев причиной ошибок.например, вы, вероятно, никогда не следует использовать его для чего-то, что возвращает массив результатов или список результатов; вместо этого верните пустой массив или список. Вы почти никогда не должны использовать его в качестве поля чего-то или параметра метода.
Я думаю, что регулярное использование его в качестве возвращаемого значения для геттеров, безусловно,будет чрезмерным.
ничего неправильно С необязательным, что его следует избегать, это просто не то, что многие люди хотят, чтобы это было, и соответственно мы были справедливо беспокоит риск чрезмерного усердного использования.
(публичное объявление: никогда вызов
Optional.getЕсли вы не можете доказать, что это никогда не будет null; вместо этого используйте один из безопасных методов, таких какorElseилиifPresent. Оглядываясь назад, мы должны были позвонитьgetчто-то вродеgetOrElseThrowNoSuchElementExceptionили что-то, что сделало его гораздо яснее, что это был очень опасный метод, который подорвал всю цельOptionalв первую очередь. Урок. (Обновление: Java 10 имеетOptional.orElseThrow(), что семантически эквивалентноget(), но чье имя больше подходит.))
проведя небольшое собственное исследование, я столкнулся с рядом вещей, которые могут подсказать, когда это уместно. Наиболее авторитетной является следующая цитата из статьи Oracle:
" важно отметить, что намерение необязательного класса не заменять каждую пустую ссылку. Вместо этого, его цель состоит в том, чтобы помочь дизайн более понятные API так что, просто прочитав подпись a способ, вы можете сказать, можно ли ожидать необязательное значение. Это заставляет вас активно разворачивать необязательный элемент, чтобы справиться с отсутствием значения." -устали от исключений нулевого указателя? Рассмотрите возможность использования Java SE 8 по желанию!
Я нашел этот отрывок из Java 8 необязательно: как его использовать
"необязательный не предназначен для использования в этих контекстах, так как он ничего нам не купит:
- в слое модели домена (не сериализуемый)
- в DTOs (по той же причине)
- во входных параметрах методов
- в параметрах конструктора"
который также, кажется, поднимает некоторые действительные моменты.
Я не смог найти никаких негативных коннотаций или красных флагов, чтобы предположить, что
Optionalследует избегать. Я думаю, что генерал идея, если это полезно и повышает удобство использования вашего API используйте его.
Я бы сказал, что в целом это хорошая идея использовать необязательный тип для возвращаемых значений, которые могут быть обнулены. Тем не менее, w.r.t. к фреймворкам я предполагаю, что замена классических геттеров дополнительными типами вызовет много проблем при работе с фреймворками (например, Hibernate), которые полагаются на соглашения о кодировании для геттеров и сеттеров.
причина
Optionalбыл добавлен в Java, потому что это:return Arrays.asList(enclosingInfo.getEnclosingClass().getDeclaredMethods()) .stream() .filter(m -> Objects.equals(m.getName(), enclosingInfo.getName()) .filter(m -> Arrays.equals(m.getParameterTypes(), parameterClasses)) .filter(m -> Objects.equals(m.getReturnType(), returnType)) .findFirst() .getOrThrow(() -> new InternalError(...));чище, чем этот:
Method matching = Arrays.asList(enclosingInfo.getEnclosingClass().getDeclaredMethods()) .stream() .filter(m -> Objects.equals(m.getName(), enclosingInfo.getName()) .filter(m -> Arrays.equals(m.getParameterTypes(), parameterClasses)) .filter(m -> Objects.equals(m.getReturnType(), returnType)) .getFirst(); if (matching == null) throw new InternalError("Enclosing method not found"); return matching;Я хочу сказать, что необязательно было написано Для поддержки функционального программирования, который был добавлен в Java в то же время. (Пример приходит любезно блог Брайана Гетца. Лучший пример может использовать
orElse()метод, так как этот код будет выдавать исключение в любом случае, но вы получите картину.)но теперь, люди используют опционально по совершенно другой причине. Они используют его для устранения недостатка в языковом дизайне. Недостаток заключается в следующем: нет способа указать, какие из параметров API и возвращаемых значений могут быть null. Это может быть упомянуто в javadocs, но большинство разработчиков даже не пишут javadocs для своего кода, и не многие будут проверять javadocs, когда они пишут. Таким образом, это приводит к большому количеству кода, который всегда проверяет нулевые значения перед их использованием, хотя они часто не могут возможно, будет null, потому что они уже были проверены повторно девять или десять раз в стеке вызовов.
Я думаю, что была реальная жажда решить этот недостаток, потому что так много людей, которые видели новый необязательный класс, предполагали, что его цель-добавить ясность в API. Вот почему люди задают такие вопросы как "геттеры должны возвращать опции?- Нет, вероятно, не должны, если только вы не ожидаете, что геттер будет использоваться в функциональном программировании, что очень маловероятно. На самом деле, если вы посмотрите, где Необязательно используется в Java API, это в основном в потоковых классах, которые являются ядром функционального программирования. (Я не проверил очень тщательно, но классы потока могут быть только место, где они используются.)
если вы планируете использовать геттер в немного функциональном коде, было бы неплохо иметь стандартный геттер и второй, который возвращает необязательный.
О, И если вам нужно, чтобы ваш класс был сериализуемым, вы абсолютно не должны использовать Необязательный.
Optionals-очень плохое решение для недостатка API, потому что a) они очень многословны, и b) они никогда не предназначались для решения этой проблемы в первую очередь.
гораздо лучшим решением проблемы API является Nullness Checker. Это обработчик аннотаций, который позволяет указать, какие параметры и возвращаемые значения могут быть null, аннотируя их с помощью @Nullable. Таким образом, компилятор может сканировать код и выяснить, если значение это может быть на самом деле null передается в значение, где null не допускается. По умолчанию предполагается, что ничто не может быть null, если оно не аннотировано так. Таким образом, вам не придется беспокоиться о нулевых значений. Передача нулевого значения параметру приведет к ошибке компилятора. Проверка объекта на null, который не может быть null, создает предупреждение компилятора. Результатом этого является изменение NullPointerException из ошибки времени выполнения в ошибку времени компиляции.
это меняет всё.
что касается ваших геттеров, не используйте опционально. И попробуйте создать свои классы так, чтобы ни один из членов не мог быть null. И, возможно, попробуйте добавить проверку Nullness в свой проект и объявить ваши геттеры и параметры setter @Nullable, если им это нужно. Я делал это только с новыми проектами. Вероятно, он создает много предупреждений в существующих проектах, написанных с большим количеством лишних тестов для null, поэтому его может быть сложно модернизировать. Но он также будет ловить много жуки. Я люблю это. Мой код намного чище и надежнее из-за этого.
(есть также новый язык, который обращается к этому. Kotlin, который компилируется в байтовый код Java, позволяет указать, может ли объект быть нулевым при его объявлении. Это более чистый подход.)
добавление к оригинальному сообщению (версия 2)
после того, как я много думал, я неохотно пришел к выводу, что это приемлемо, чтобы вернуться необязательным на одном условие: полученное значение может быть нулем. Я видел много кода, где люди обычно возвращают необязательные из геттеров,которые не могут вернуть null. Я рассматриваю это как очень плохую практику кодирования, которая только добавляет сложности коду, что делает ошибки более вероятными. Но когда возвращаемое значение может быть на самом деле null, продолжайте и оберните его внутри необязательного.
имейте в виду, что методы, которые предназначены для функционального программирования, и которые требуют функция ссылка, будет (и должна) быть написана в двух формах, одна из которых использует необязательный. Например,
Optional.map()иOptional.flatMap()оба берут ссылки на функции. Первый принимает ссылку на обычный геттер, а второй принимает тот, который возвращает необязательный. Таким образом, вы не делаете никому одолжение, возвращая необязательное значение, где значение не может быть null.сказав Все это, я все еще вижу подход, используемый Nullness Checker это лучший способ борьбы с нулями, так как они превращаются Возникновению исключительных ситуаций типа NullPointerException во время выполнения ошибки Ошибки времени компиляции.
если вы используете современные сериализаторы и другие фреймворки, которые понимают
Optionalтогда я нашел эти рекомендации хорошо работать при написанииEntityбобы и доменные слои:
- если уровень сериализации (обычно БД) позволяет
nullзначение ячейки в столбцеBARв таблицеFOO, то геттерFoo.getBar()может возвратитьOptionalуказание разработчику, что это значение может разумно ожидаться как null и они должны справиться с этим. Если БД гарантирует, что значение не будет равно null, то геттер должен не обернуть вOptional.Foo.barдолжно бытьprivateи не бытьOptional. Там действительно нет причин для этого, чтобы бытьOptionalЕсли этоprivate.- сеттер
Foo.setBar(String bar)должен принимать типbarи неOptional. Если это нормально использоватьnullаргумент затем укажите это в комментарии JavaDoc. Если это не нормально использоватьnullanIllegalArgumentExceptionили какая-то подходящая бизнес-логика, ИМХО, более подходящая.- конструкторы не нужны
Optionalаргументы (по причинам, аналогичным пункту 3). Как правило, я включаю только аргументы в конструктор, который должны иметь значение null в базе данных сериализации.чтобы сделать вышеописанное более эффективным, вы можете отредактировать свои шаблоны IDE для создания геттеров и соответствующих шаблонов для
toString(),equals(Obj o)etc. или используйте поля непосредственно для них (большинство генераторов IDE уже имеют дело с нулями).
Comments