Почему Cloneable не устарел?

Общеизвестно, что интерфейс Cloneable в Java нарушен. Для этого есть много причин, о которых я не буду говорить; другие уже сделали это. Это также позиция архитекторов Java.

Поэтому мой вопрос: почему еще не устарели? Если основная команда Java решила, что она сломана, тогда они также должны были подумать об устаревании. Каковы их причины против этого (в Java 8 он все еще не устарел)?

Ответ 1

В bug, представленном в 1997 году База данных Java Bug о добавлении метода clone() до Cloneable, так что это уже не будет бесполезно. Он был закрыт с разрешением "не исправить", и оправдание было следующим:

Комитет по техническому обзору ВС (TRC) рассмотрел этот вопрос подробно и рекомендовал не принимать любые действия, кроме улучшения документация текущего интерфейса Cloneable. Вот полный текст рекомендации:

Существующие API-интерфейсы клонирования объектов Java являются проблематичными. Eсть защищенный метод "клонировать" на java.lang.Object и есть интерфейс java.lang.Cloneable. Цель состоит в том, что если класс хочет разрешить других людей, чтобы клонировать его, тогда он должен поддерживать Cloneable интерфейса и переопределить метод защищенного клона по умолчанию с помощью общедоступный метод клонирования. К сожалению, по причинам, туман времени, интерфейс Cloneable не определяет клон Метод.

Эта комбинация приводит к большому количеству путаницы. Некоторые классы заявить о поддержке Cloneable, но случайно забыть поддержать клон. Разработчики сбиты с толку о том, как предполагается Cloneable работать и то, что должен делать клоун.

К сожалению, добавление метода клонирования к Cloneable будет несовместимые изменения. Он не нарушит двоичную совместимость, но он будет совместимость источника прерываний. Анекдотические данные свидетельствуют о том, что в практики существует ряд случаев, когда классы поддерживают Клонируемый интерфейс, но не обеспечивает общедоступный метод клонирования. После обсуждения, TRC единодушно рекомендовал, чтобы мы не существующий Cloneable интерфейс, из-за влияния совместимости.

Альтернативное предложение заключалось в том, чтобы добавить новый интерфейс java.lang.PubliclyCloneable, чтобы отразить первоначальную цель от Cloneable. От 5 до 2 большинства, TRC рекомендовал против этого. Основная проблема заключалась в том, что это добавит еще больше путаницы (в том числе орфографическая путаница!) к уже запутанной картине.

TRC единогласно рекомендовал добавить дополнительные документацию к существующему интерфейсу Cloneable, чтобы лучше описать как он предназначен для использования и для описания "лучших практик" для реализаторы.

Итак, хотя это не относится к устаревшим причинам, причина не в том, что Cloneable "устарела", так это то, что Technical Review Comitee решил, что изменение существующей документации будет достаточно [], чтобы сделать этот интерфейс полезным. И так они и сделали. До того, как Java 1.4, Cloneable был зарегистрирован следующим образом:

Класс реализует интерфейс Cloneable для указания на Object.clone(), что законным для этого метода является поле для копирования экземпляров этого класса.

Попытки клонировать экземпляры, которые не реализуют Cloneable интерфейс приводит к исключению CloneNotSupportedException, являющемуся выброшены.

Интерфейс Cloneable не объявляет никаких методов.

Так как Java 1.4 (который был выпущен в феврале 2002 года) до текущей версии (Java 8), он выглядит следующим образом:

Класс реализует интерфейс Cloneable для указания на Object.clone(), что законным для этого метода является поле для копирования экземпляров этого класса. Вызов объекта clone на экземпляре, который не реализует Cloneable интерфейс приводит к исключению CloneNotSupportedException, являющемуся выброшены.

По соглашению классы, реализующие этот интерфейс, должны переопределить Object.clone(который защищен) с помощью общедоступного метода. Видеть Object.clone() для получения дополнительной информации об переопределении этого метода.

Обратите внимание, что этот интерфейс не содержит метода клонирования. Следовательно, невозможно клонировать объект только в силу факта что он реализует этот интерфейс. Даже если вызывается метод clone Отрадно, что нет гарантии, что это будет успешным.

Ответ 2

Краткий ответ на вопрос "Почему не Cloneable устарел?" (или, действительно, почему не X устарел, для любого X) заключается в том, что не уделялось много внимания их осуждению.

Большинство вещей, которые были устаревшими в последнее время, были устаревшими, поскольку существует конкретный план их удаления. Например, методы addPropertyChangeListener и removePropertyChangeListener LogManager были устарел в Java SE 8 с намерением удалить их в Java SE 9. (Причина в том, что они излишне усложняют взаимоблокировки модулей.) Действительно, эти API уже были удалено из ранних версий JDK 9. (Обратите внимание, что аналогичные вызовы прослушивателя смены свойств также были удалены из Pack200, см. JDK-8029806.)

Подобного плана не существует для Cloneable и Object.clone().

Более длинный ответ будет включать обсуждение дополнительных вопросов, таких как то, что можно ожидать от этих API, какие затраты или выгоды будут начисляться на платформу, если они устарели, и то, что сообщается разработчикам, когда API устарел. Я изучил эту тему в своем недавнем разговоре JavaOne, Долг и устаревание. (Слайды доступны по этой ссылке, здесь).) Оказывается, сам JDK не очень последователен в использовании устаревания. Это означало несколько разных вещей, в том числе, например,

  • Это опасно, и вы должны знать о рисках его использования (пример: Thread.stop(), Thread.resume() и Thread.suspend()).

  • Это будет удалено в будущей версии

  • Это устарело, и вам будет полезно использовать что-то другое (например: многие из методов в java.util.Date)

Все это разные значения, а разные подмножества из них относятся к разным устаревшим вещам. И некоторые подмножества из них относятся к вещам, которые не устарели (но это, возможно, должно быть устаревшим).

Cloneable и Object.clone() "сломаны" в том смысле, что у них есть недостатки дизайна и их трудно использовать правильно. Тем не менее, clone() по-прежнему является лучшим способом копирования массивов, а клонирование имеет ограниченную полезность для копирования экземпляров классов, которые были тщательно реализованы. Удаление клонирования было бы несовместимым изменением, которое нарушило бы многие вещи. Операцию клонирования можно переопределить другим способом, но она, вероятно, будет медленнее, чем Object.clone().

Однако для большинства вещей конструктор копирования предпочтительнее клонирования. Поэтому, возможно, было бы целесообразно обозначить Cloneable как "устаревшее" или "замещенное" или что-то подобное. Это говорит разработчикам, что они, вероятно, захотят посмотреть в другом месте, но это не будет означать, что механизм клонирования может быть удален в будущей версии. К сожалению, такой маркер не существует.

Как бы то ни было, "устаревание", по-видимому, подразумевает возможное удаление - несмотря на то, что исчезающе небольшое количество устаревших функций когда-либо удалялось - и поэтому для механизма клонирования не представляется оправданием. Возможно, в будущем может быть применена альтернативная маркировка, которая позволяет разработчикам вместо этого использовать альтернативные механизмы.

UPDATE

Я добавил дополнительную историю в отчет об ошибке . Фрэнк Еллин, ранний разработчик JVM и соавтор спецификации JVM, сделал несколько комментариев в ответ на комментарий "потерянный в тумане времени" в рекомендации TRC, приведенный в другом ответить. Я процитировал соответствующие части здесь; полное сообщение находится в отчете об ошибке.

Cloneable не имеет методов по той же причине, что и Serializable. Cloneable указывает свойство класса, а не конкретно говорит что-либо о методах, поддерживаемых классом.

До отражения нам понадобился собственный метод для создания мелкой копии объекта. Следовательно, появился Object.clone(). Было также ясно, что многие классы захотят переопределить этот метод и что не каждый класс захочет клонировать. Следовательно, Cloneable родился, чтобы указать намерение программиста.

Итак, короче. Цель Cloneable заключалась не в том, чтобы указать, что у вас был общедоступный метод clone(). Это должно было указывать на то, что вы были готовы к клонированию с помощью Object.clone(), и для реализации было необходимо решить, следует ли делать clone() public.

Ответ 3

почему он еще не устарел?

Поскольку JCP не счел нужным сделать это и никогда не сможет этого сделать. Спроси их. Вы спрашиваете не в том месте.

Каковы причины сохранения этой вещи в Java API

Никто не удалит что-либо из Java API из-за требования обратной совместимости. В последний раз это произошло с изменением модели событий AWT между 1.0 и 1.1 в 1996/7 году.