Ответ 1
Приведенный вами пример не является подходящим вариантом использования Необязательно. Пустой Необязательный представляет значение, которое отсутствует по причине, которая не может быть предсказана вызывающим. Это результат юридического вызова метода.
Код, который вы представляете как "старая идиома", выполняет проверку ввода и выдает исключение, если вход недействителен. Это поведение должно оставаться неизменным, даже если вы вводите опцию. Единственное различие заключается в том, что возвращаемое значение Object get(i)
возможно равно нулю, тогда как возвращаемое значение Optional<?> get(i)
никогда не является нулевым, поскольку существует специальное состояние экземпляра Option, представляющего отсутствие значения.
Преимущество методов, которые возвращают Необязательный вместо значения NULL, - это устранение кода шаблона, который должен выполнить обычную проверку нулевого уровня, прежде чем пытаться что-либо сделать с возвращаемым значением. Есть гораздо больше преимуществ в использовании Необязательно исключительно внутри метода. Например:
static Optional<Type> componentType(Type type) {
return Optional.of(type)
.filter(t -> t instanceof ParameterizedType)
.map(t -> (ParameterizedType) t)
.filter(t -> t.getActualTypeArguments().length == 1)
.filter(t -> Optional.of(t.getRawType())
.filter(rt -> rt instanceof Class)
.map(rt -> (Class<?>) rt)
.filter(Stream.class::isAssignableFrom)
.isPresent())
.map(t -> t.getActualTypeArguments()[0]);
Здесь важное преимущество - прекрасный контроль над областью: одно и то же имя t
повторно используется в каждой новой области для переменной типа, подходящего для этого этапа обработки. Таким образом, вместо того, чтобы быть вынужденным иметь переменные по охвату после истечения срока их полезного использования и изобретать новое имя для каждой следующей переменной, с этой идиомой мы имеем точный минимум, который нам нужно продолжить.
Просто для интереса вы можете реализовать equals
полностью в терминах Необязательно:
@Override public boolean equals(Object obj) {
return Optional.ofNullable(obj)
.filter(that -> that instanceof Test)
.map(that -> (Test)that)
.filter(that -> Objects.equals(this.s1, that.s1))
.filter(that -> Objects.equals(this.s2, that.s2))
.isPresent();
}
Хотя я считаю эту идиому очень чистой и удобочитаемой, она в настоящее время не оптимизирована, чтобы ее можно было рекомендовать как достойный выбор. Однако будущие версии Java могут сделать это жизнеспособным.