Почему опция <T> объявлена как последний класс?
Я играл со следующим вопросом: Используя необязательный вариант Java 8 с Stream:: flatMap и хотел добавить метод к пользовательскому Optional<T>
, а затем проверить, если это сработало.
Точнее, я хотел добавить stream()
в мой CustomOptional<T>
, который возвращает пустой поток, если значение отсутствует, или поток с одним элементом, если он присутствует.
Однако я пришел к выводу, что Optional<T>
объявляется окончательным.
Почему это так? Есть множество классов, которые не объявлены окончательными, и я лично не вижу здесь причины объявлять Optional<T>
final.
Изменить, как второй вопрос, почему все методы не могут быть окончательными, если беспокоиться о том, что они будут переопределены и оставить класс не окончательным?
Ответы
Ответ 1
Согласно эта страница документов Java SE 8 API, Optional<T>
- это класс, основанный на значении. В соответствии с этой страницей документации API классы, основанные на значении, должны быть неизменными.
Объявление всех методов в Optional<T>
как final предотвратит переопределение методов, но это не помешает расширяющему классу добавлять поля и методы. Расширение класса и добавление поля вместе с методом, который изменяет значение этого поля, сделает этот подкласс измененным и, следовательно, позволит создать изменяемый Optional<T>
. Ниже приведен пример такого подкласса, который может быть создан, если Optional<T>
не будет объявлен окончательным.
//Example created by @assylias
public class Sub<T> extends Optional<T> {
private T t;
public void set(T t) {
this.t = t;
}
}
Объявление Optional<T>
final предотвращает создание подклассов, подобных выше, и, следовательно, гарантирует, что Optional<T>
всегда неизменен.
Ответ 2
Вероятно, причина та же, что и почему String
является окончательным; то есть, чтобы все пользователи класса Optional
могли быть уверены, что методы экземпляра, который они получают, сохраняют в своем контракте всегда возвращающее одно и то же значение.
Ответ 3
Как утверждали другие, необязательный - это класс, основанный на значении, и поскольку он является классом, основанным на значении, он должен быть неизменным, что требует его окончательного.
Но мы упустили момент для этого. Одной из основных причин, почему классы, основанные на значении, являются неизменяемыми, является гарантировать безопасность потоков. Обеспечение его неизменности делает его потокобезопасным. Возьмите, например, String или примитивные обертки, такие как Integer или Float. Они объявлены окончательными по тем же причинам.
Ответ 4
-
Нет необходимости в подклассе этого класса. Вы можете выполнить то, что хотите, составив существующие методы. в вашем случае это метод map
или flatMap
.
-
объявив класс final
, вы эффективно объявляете все методы final
.