Почему метод clone () защищен в java.ленг.Объект?

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

11 ответов


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

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

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

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

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

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


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

От Солнца:

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


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


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

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

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


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

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


из javadoc из клонируемые.

* 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.

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


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

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

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

Это protected.

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


метод Clone () имеет внутреннюю проверку "экземпляр Cloneable или нет".Вот как команда Java может подумать, что ограничит неправильное использование метода clone ().метод clone () защищен, т. е. доступен только подклассам. Поскольку object является родительским классом всех подклассов, метод Clone () может использоваться всеми классами infact, если у нас нет выше проверки "экземпляра Cloneable". Это причина, по которой команда Java могла подумать ограничить неправильное использование clone (), выполнив регистрацию метод clone () "является ли он экземпляром Cloneable".

следовательно, любые классы, реализующие cloneable, могут использовать метод clone () класса объектов.

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


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

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;
    }
}

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


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

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


опять же, Java JDK framework показывает блестящее мышление:

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

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