Причина 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;
Я хочу сказать, что Optional был написан для поддержки функционального программирования , которое было добавлено в Java в то же время. (Этот пример любезно предоставлен блогом Брайана Гетца . Лучшим примером может быть использование orElse()
метода, так как этот код в любом случае вызовет исключение, но вы получите представление.)
Но сейчас люди используют Optional по совсем другой причине. Они используют это для устранения недостатка в дизайне языка. Недостаток заключается в следующем: невозможно указать, какие из параметров API и возвращаемые значения могут быть нулевыми. Это может быть упомянуто в javadocs, но большинство разработчиков даже не пишут javadocs для своего кода, и не многие проверяют javadocs при их написании. Таким образом, это приводит к большому количеству кода, который всегда проверяет наличие нулевых значений перед их использованием, даже если они часто не могут быть нулевыми, поскольку они уже неоднократно проверялись девять или десять раз в стеке вызовов.
Я думаю, что была настоящая жажда устранить этот недостаток, потому что так много людей, которые видели новый класс Optional, предполагали, что его цель - внести ясность в API. Вот почему люди задают такие вопросы, как «должен ли получатель вернуть опционально?» Нет, они, вероятно, не должны, если вы не ожидаете, что геттер будет использоваться в функциональном программировании, что очень маловероятно. Фактически, если вы посмотрите, где Optional используется в Java API, то это в основном в классах Stream, которые являются ядром функционального программирования. (Я не очень тщательно проверил, но классы Stream могут быть единственным местом, где они используются.)
Если вы планируете использовать метод получения в небольшом количестве функционального кода, было бы неплохо иметь стандартный метод получения и второй метод, возвращающий Optional.
Да, и если вам нужно, чтобы ваш класс был сериализуемым, вы не должны использовать Optional.
Необязательные решения являются очень плохим решением для недостатка API, потому что они очень многословны и б) они никогда не предназначались для решения этой проблемы.
Гораздо лучшим решением для недостатка API является Nullness Checker . Это процессор аннотаций, который позволяет вам указать, какие параметры и возвращаемые значения могут иметь значение null, пометив их @Nullable. Таким образом, компилятор может сканировать код и выяснить, передается ли значение, которое может фактически быть нулевым, значению, для которого нулевое значение не допускается. По умолчанию предполагается, что ничто не может быть пустым, если это не аннотировано. Таким образом, вам не нужно беспокоиться о нулевых значениях. Передача нулевого значения параметру приведет к ошибке компилятора. Тестирование объекта на нулевое значение, которое не может быть нулевым, выдает предупреждение компилятора. Результатом этого является изменение NullPointerException от ошибки времени выполнения до ошибки времени компиляции.
Это меняет все.
Что касается ваших добытчиков, не используйте Optional. И попробуйте создать свои классы, чтобы ни один из участников не мог быть нулевым. И, возможно, попробуйте добавить Nullness Checker в ваш проект и объявить ваши методы получения и установки @Nullable, если они в этом нуждаются. Я сделал это только с новыми проектами. Он, вероятно, выдает много предупреждений в существующих проектах, написанных с множеством лишних тестов на ноль, поэтому может быть сложно модернизировать. Но это также поймает много ошибок. Я люблю это. Мой код намного чище и надежнее из-за этого.
(Существует также новый язык, который решает эту проблему. Kotlin, который компилируется в байт-код Java, позволяет вам указать, может ли объект быть нулевым, когда вы объявляете его. Это более чистый подход.)
Приложение к Исходному сообщению (версия 2)
После долгих размышлений я неохотно пришел к выводу, что допустимо возвращать Optional при одном условии: что полученное значение может фактически быть нулевым. Я видел много кода, где люди обычно возвращают Optional от получателей, которые не могут вернуть null. Я считаю это очень плохой практикой кодирования, которая только добавляет сложности к коду, что повышает вероятность ошибок. Но когда возвращаемое значение может фактически быть нулевым, продолжайте и оберните его внутри Необязательного.
Помните, что методы, предназначенные для функционального программирования и требующие ссылки на функцию, будут (и должны) записываться в двух формах, одна из которых использует Optional. Например, Optional.map()
и Optional.flatMap()
те , и другие берут ссылки на функции. Первый принимает ссылку на обычный получатель, а второй принимает тот, который возвращает Необязательный. Таким образом, вы никому не делаете одолжение, возвращая Optional, где значение не может быть нулевым.
Сказав все это, я все еще вижу, что подход, применяемый средством проверки на нулевое значение, является лучшим способом справиться с пустыми значениями, поскольку они превращают исключения NullPointerException из ошибок времени выполнения в ошибки времени компиляции.