Краткий ответ на вопрос "почему не Cloneable
устарел?" (или, действительно, почему они не являются X
устаревшими X
), заключается в том, что их устареванию не уделялось много внимания.
Большинство вещей, которые недавно были объявлены устаревшими, устарели, потому что существует специальный план их удаления. Например, методы addPropertyChangeListener
и LogManager были объявлены устаревшими в Java SE 8 с намерением удалить их в Java SE 9. (Причина в том, что они излишне усложняли взаимозависимости модулей). Действительно, эти API уже были удалены из ранней разработки JDK 9. строит. (Обратите внимание, что аналогичные вызовы прослушивателя изменения свойств также были удалены ; см. JDK-8029806 .)removePropertyChangeListener
Pack200
Подобных планов не существует для Cloneable
и Object.clone()
.
Более подробный ответ будет включать обсуждение дополнительных вопросов, например, что можно ожидать от этих API-интерфейсов, какие затраты или выгоды понесет платформа, если они станут устаревшими, и что сообщается разработчикам, когда API устаревает. Я исследовал эту тему в моем недавнем выступлении JavaOne « Долг и устаревание» . (Слайды доступны по этой ссылке; видео здесь .) Оказывается, сам JDK не очень последовательно использовал устаревание. Он использовался для обозначения нескольких разных вещей, в том числе, например,
Это опасно , и вы должны быть осведомлены о рисках , связанных с использованием (пример: Thread.stop()
, Thread.resume()
, и Thread.suspend()
).
Это будет удалено в следующем выпуске
Это устарело, и вам рекомендуется использовать что-то другое (пример: многие методы в java.util.Date
)
Все они имеют разные значения, и разные подмножества из них относятся к разным устаревшим вещам. И некоторые из них применимы к вещам, которые не являются устаревшими (но, возможно, их следует исключить).
Cloneable
и Object.clone()
являются «сломанными» в том смысле, что имеют конструктивные недостатки и их трудно правильно использовать. Однако clone()
это по-прежнему лучший способ копирования массивов, и клонирование имеет ограниченную полезность для создания копий экземпляров тщательно реализованных классов. Удаление клонирования было бы несовместимым изменением, которое сломало бы многие вещи. Операцию клонирования можно было бы реализовать другим способом, но, вероятно, это будет медленнее, чем Object.clone()
.
Однако в большинстве случаев конструктор копирования предпочтительнее клонирования. Так что, возможно, Cloneable
будет уместна отметка «устаревшее» или «замененное» или что-то подобное. Это скажет разработчикам, что они, вероятно, захотят поискать в другом месте, но не будет сигналом того, что механизм клонирования может быть удален в будущем выпуске. К сожалению, такого маркера не существует.
В настоящее время «устаревание», похоже, подразумевает окончательное удаление - несмотря на то, что когда-либо было удалено исчезающе небольшое количество устаревших функций, - и поэтому отказ от поддержки механизма клонирования не кажется оправданным. Возможно, в будущем можно будет применить альтернативную маркировку, которая заставит разработчиков использовать альтернативные механизмы.
ОБНОВИТЬ
Я добавил дополнительную историю в отчет об ошибке . Фрэнк Йеллин, один из первых разработчиков JVM и соавтор спецификации JVM, сделал несколько комментариев в ответ на комментарий «затерянный в тумане времени» в рекомендации TRC, цитируемый в другом ответе . Я процитировал здесь соответствующие части; полное сообщение находится в отчете об ошибке.
В Cloneable нет методов по той же причине, что и у Serializable. Cloneable указывает свойство класса, а не говорит что-либо конкретно о методах, поддерживаемых классом.
Перед отражением нам нужен был собственный метод для создания неглубокой копии объекта. Так родился Object.clone (). Также было ясно, что многие классы захотят переопределить этот метод и что не каждый класс захочет клонировать. Следовательно, Cloneable родился, чтобы указать на намерение программиста.
Итак, короче. Цель Cloneable не состояла в том, чтобы указать, что у вас есть общедоступный метод clone (). Это должно было указать, что вы готовы к клонированию с помощью Object.clone (), и реализация должна была решить, делать clone () общедоступным или нет.