Почему метод clone() защищен в java.lang.Object?

Какова конкретная причина, по которой clone() определяется как защищенная в java.lang.Object?

Ответ 1

Тот факт, что клон защищен, крайне сомнительный - как и тот факт, что метод clone не объявлен в интерфейсе Cloneable.

Это делает метод довольно бесполезным для копирования данных, потому что вы не можете сказать:

if(a instanceof Cloneable) {
    copy = ((Cloneable) a).clone();
}

Я думаю, что дизайн Cloneable теперь в значительной степени рассматривается как ошибка (цитата ниже). Обычно я хотел бы иметь возможность реализовать реализации интерфейса Cloneable, но не обязательно сделать интерфейс Cloneable (аналогично использованию Serializable). Это невозможно сделать без отражения:

ISomething i = ...
if (i instanceof Cloneable) {
   //DAMN! I Need to know about ISomethingImpl! Unless...
   copy = (ISomething) i.getClass().getMethod("clone").invoke(i);
}

Цитата из Джош Блох Эффективная Java:
"Интерфейс Cloneable был предназначен как интерфейс mixin для рекламы объектов, которые разрешают клонирование. К сожалению, это не подходит для этой цели... Это очень атипичное использование интерфейсов, а не эмулирование... Для реализации интерфейс, который будет иметь какое-либо влияние на класс, он и все его суперклассы должны подчиняться довольно сложному, невыполнимому и в основном недокументированному протоколу"

Ответ 2

Интерфейс Clonable - это всего лишь маркер, говорящий, что класс может поддерживать клон. Метод защищен, потому что вы не должны называть его объектом, вы можете (и должны) переопределить его как общедоступный.

От Солнца:

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

Ответ 3

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

Ответ 4

Метод Clone нельзя напрямую использовать для любого объекта, поэтому он должен быть переопределен подклассом.

Конечно, он может быть общедоступным и просто бросать соответствующее исключение, когда клонирование невозможно, но я думаю, что это будет вводить в заблуждение.

Способ клонирования реализован прямо сейчас, заставляет вас задуматься о том, почему вы хотите использовать клон и как клонировать ваш объект.

Ответ 5

Он защищен, потому что реализация по умолчанию выполняет мелкую попористую копию всех полей (включая частные), обходя конструктор. Это не то, что объект может быть разработан для обработки в первую очередь (например, он может отслеживать созданные экземпляры объектов в общем списке или что-то подобное).

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

Ответ 6

Из javadoc cloneable.

* By convention, classes that implement this interface (cloneable) should override 
* <tt>Object.clone</tt> (which is protected) with a public method.
* See {@link java.lang.Object#clone()} for details on overriding this
* method.

* Note that this interface does <i>not</i> contain the <tt>clone</tt> method.
* Therefore, it is not possible to clone an object merely by virtue of the
* fact that it implements this interface.  Even if the clone method is invoked
* reflectively, there is no guarantee that it will succeed.

Таким образом, вы можете вызывать клон для каждого объекта, но это даст вам большую часть времени, а не результаты, которые вы хотите или исключение. Но это только поощряется, если вы реализуете клонирование.

Ответ 7

ИМХО это так просто:

  • #clone не следует вызывать на не клонируемых объектах, поэтому он не становится общедоступным
  • #clone должен быть вызван подклассами ob Object, которые реализуют Cloneable, чтобы получить мелкую копию правого класса

Какая правильная область для методов, которые должны быть вызваны подклассами, но не другими классами?

Это protected.

Классы, реализующие Cloneable, конечно, сделают этот метод общедоступным, чтобы его можно было вызывать из других классов.

Ответ 8

NB: я не знаю о java.lang.Object

но когда ваш класс реализует шаблон singleton, тогда его необходимо защитить клон, wakeup конструктор и т.д. function bcz, вы также можете создавать новые экземпляры

Ответ 9

Да, та же проблема, что и я. Но я решаю это, реализуя этот код

public class Side implements Cloneable {
    public Side clone() {

        Side side = null;
        try {
            side = (Side) super.clone();
        } catch (CloneNotSupportedException e) {
            System.err.println(e);
        }
        return side;
    }
}

Так же, как раньше кто-то сказал.

Ответ 10

Ну, также разработчики солнца только люди, и они действительно сделали огромную ошибку, чтобы реализовать метод clone как защищенный, ту же ошибку, что и внедренный в ArrayList неработающий метод клонирования! Таким образом, в целом существует гораздо более глубокое недоразумение даже опытных программистов Java о методе клонирования.

Однако я недавно нашел быстрое и простое решение для копирования любого объекта со всем его содержимым, независимо от того, как он построен и что он содержит, см. мой ответ здесь: Ошибка при использовании Object.clone()

Ответ 11

Снова структура Java JDK показывает блестящее мышление:

Клонируемый интерфейс не содержит "public T clone();" потому что он больше похож на атрибут (например, Serializable), который позволяет клонировать экземпляр.

В этом дизайне нет ничего плохого, потому что:

  • Object.clone() не будет делать то, что вы хотите, с вашим пользовательским классом.

  • Если вы используете Myclass Cloneable = > , вы переписываете clone() с помощью "public MyClass clone()"

  • Если у вас есть MyInterface расширяет Cloneable и некоторые MyClasses, реализующие MyInterface: просто определите "public MyInterface clone();" в интерфейсе, и каждый метод с использованием объектов MyInterface сможет клонировать их независимо от их класса MyClass.