Почему java.lang.Cloneable не переопределяет метод clone () в java.lang.Object? - PullRequest
6 голосов
/ 02 апреля 2012

Спецификация Java для интерфейса java.lang.Cloneable определяет себя как означающее, что любой объект, который его расширяет, также реализовал метод clone(), который находится в состоянии покоя в java.lang.Object. В частности, это говорит о том, что:

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

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

public static makeACloneFrom(Cloneable c)
{
  return c.clone();
}

однако, это не тот случай, так как весь исходный код Cloneable (sans javadoc) просто

package java.lang;

public interface Cloneable {
}

Это означает, что Cloneable#clone() не существует (и попытка скомпилировать приведенный выше пример метода приводит к ошибке времени компиляции, говорящей что-то вроде "cannot find symbol: method clone()"). Не должен ли исходный код Cloneable содержать что-либо с эффектом public Cloneable clone();?

Почему нельзя допустить, чтобы класс, реализующий Cloneable, имел метод public Cloneable clone()?

Ответы [ 2 ]

6 голосов
/ 02 апреля 2012

Тьфу. clone и Cloneable сломаны, ужасно спроектированы и не должны использоваться в новом коде. (См. Эффективный элемент Java 11.)

Причиной этой конкретной вещи является то, что Cloneable представляет собой запутанно реализованный магический интерфейс, такой, что простой акт реализации Cloneable изменяет поведение Object.clone с помощью отражения. Эффективная Java говорит:

... если класс реализует метод Cloneable, Object ’s clone возвращает полевую копию объекта; в противном случае он создает исключение CloneNotSupportedException. Это очень нетипичное использование интерфейсов, а не подражание ...

5 голосов
/ 02 апреля 2012

Потому что это плохо спроектированный интерфейс.

С Эффективная Java (извините, в Google Книгах нет предварительного просмотра для 2-го издания):

Пункт 11: Переопределить clone разумно

Интерфейс Cloneable был задуман как смешанный интерфейс (Элемент 18) для объектов, рекламирующих, что они разрешают клонирование. К несчастью, он не служит этой цели. Его основной недостаток в том, что ему не хватает clone метод и Object 'clone метод защищены. Вы не может, прибегая к отражению (пункт 53), вызвать clone Метод объекта только потому, что он реализует Cloneable. Даже рефлексивный вызов может потерпеть неудачу, так как нет гарантии, что Объект имеет доступный метод clone.

...