Какова конкретная причина, по которой 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
должен быть вызван подклассами obObject
, которые реализуют 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.