Клонируемое поведение
Java документ говорит -
Класс Object сам по себе не реализует интерфейс Cloneable, поэтому вызов метода clone для объекта, класс которого Object, приведет к возникновению исключения во время выполнения.
Вот почему метод клонирования в классе Object защищен? это так?
Это означает, что любой класс, который не реализует cloneable, будет вызывать исключение CloneNotSupported, когда вызывается его метод clone.
Я запустил тестовую программу
public class Test extends ABC implements Cloneable{
@Override
public Object clone() throws CloneNotSupportedException {
System.out.println("calling super.clone");
return super.clone();
}
public static void main(String[] args) {
Test t = new Test();
try{
t.clone();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
class ABC{
}
Из Class Test клона метод super.clone вызывается?
Почему это не исключение?
6 ответов
Дерево наследования Test
пример t
похоже
Object
ABC
Test
Test
также реализует Cloneable
Это означает, что когда вы вызываете метод super.clone()
Object
"s clone
метод будет вызван. Он проверяет, если экземпляр t
реализует Cloneable
интерфейс. Поскольку он реализует метод, не генерирует исключение.
Я бы сказал хороший вопрос, чтобы сбить с толку интервьюируемых:).
Насколько причина, почему это не бросает исключение. Думайте об этом объектным способом. Ваш объект t имеет класс Test, который реализует клонируемый. Когда вы вызываете метод super.clone, он все еще является объектом класса Test, и поэтому нет никаких причин для того, чтобы он вызывал исключение CloneNotSupported. Если бы это был объект класса Object, он бы выдал исключение.
Интерфейс Cloneable - это интерфейс маркера, который указывает, что реализующий класс поддерживает метод clone. Причина, по которой super.clone() не генерирует исключение, заключается в том, что базовый объект, к которому он вызывается, является клонируемым по наследству.
Из Javadoc:
Класс реализует интерфейс Cloneable, чтобы указать методу Object.clone(), что для этого метода допустимо делать копию поля для поля экземпляров этого класса.
Вызов метода clone объекта в экземпляре, который не реализует интерфейс Cloneable, приводит к исключению CloneNotSupportedException.
Потому что ваш класс реализует Cloneable
, От Javadoc Cloneable
:
Класс реализует интерфейс Cloneable, чтобы указать методу Object.clone(), что для этого метода допустимо делать копию поля для поля экземпляров этого класса.
Так что это позволяет использовать Object
"s clone()
метод. Это (опять же в соответствии с Javadoc) просто соглашение, чтобы переопределить clone()
, Если вы не переопределите его и Object
"s clone()
метод выполняет копирование поля для поля, вы все равно можете получить CloneNotSupportedException
если одно из полей само не является клонируемым. Поэтому это хороший совет, чтобы отменить это.
Почему метод клонирования в классе Object
protected
?
Таким образом, класс, который выбирает поддержку клонирования, не обязан выставлять его в своем публичном API.
Как показывает ваш пример, подкласс может переопределять метод с более широким доступом, чем унаследованная версия метода. Вы просто не можете уменьшить доступ метода таким способом.
Это означает, что любой класс, который не реализует cloneable, будет вызывать исключение CloneNotSupported, когда вызывается его метод clone.
Это правильно.
Из Class Test клона метод super.clone вызывается?
Это правильно.
Почему это не исключение?
Потому что вы объявили, что ваш класс реализует Cloneable
, Если бы вы этого не сделали, было бы сгенерировано исключение... при условии, что ваш метод клонирования по-прежнему вызывается super.clone()
,
Это может дать вам ответ на вопрос, почему защищен метод, почему защищен метод клонирования?
Это не вызывает исключения, потому что вы реализуете Cloneable. Из клонируемой документации:
"Класс реализует интерфейс Cloneable, чтобы указать методу Object.clone(), что для этого метода допустимо делать копию поля для поля экземпляров этого класса. Вызов метода клона Object для экземпляра, который не реализует интерфейс Cloneable приводит к исключению CloneNotSupportedException. "
Но когда вы его реализуете, вы говорите реализации Object, что разрешено делать копию поля для поля, чтобы она не вызывала исключение.