Object clone = x.clone();
Это клон(копия) объекта класса Date.
Дальше его нужно привести к типу Date
Date cloneDate = (Date) clone;
Почему clone() возвращает Object ? - потому как этот метод наследуется от класса Object, а так как все типы в джаве наследуют класс Object, следовательно clone() должен возвращать общий для всех типов тип - Object
UPDATE:
Для начала нужно разобраться, почему же все таки нужно переопределять метод clone(), а не воспользоватся наследуемой нативной реализацией данного метода. Все дело в том, что базовый метод клонирование выполняет только поверхностное копирование. Будут скопированные только значения полей класса. Для примитивных типов (int, byte, char), все будет норм, но если это массивы, коллекции, объекты (например Date), или ваши типы, то будут скопированы только ссылки на них. В итогу клонирования у нас будет два объекта, у которых поля ссылаются на одни и те же поля, и через эти поля можно повлиять на все объекты которые клонировались:
class TestClone implements Cloneable {
private Date date = new Date();
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
TestClone a = new TestClone();
TestClone b = (TestClone) a.clone();
System.out.println(a.getDate());
System.out.println(b.getDate());
b.getDate().setYear(0);
System.out.println(a.getDate());
System.out.println(b.getDate());
// Fri Jul 10 23:13:47 EEST 2015
// Fri Jul 10 23:13:47 EEST 2015
// изменили один, а поменялось два
// Tue Jul 10 23:13:47 EET 1900
// Tue Jul 10 23:13:47 EET 1900
Такое не пройдет, если будут
неизменяемые (immutable) классы, тот же String. У него нет методов для изменения состояния.
Потому то и нужно переопределять метод clone и выполнять глубокое копирование всех изменяемых объектов на который ссылаются поля (если есть такие).
class TestClone implements Cloneable {
private Date date = new Date();
private String s = "string"; // этот не нужно клонировать
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
@Override
protected Object clone() throws CloneNotSupportedException {
TestClone clone = (TestClone) super.clone();
if (this.date != null) {
clone.date = (Date) this.date.clone();
}
return clone;
}
}
Fri Jul 10 23:25:16 EEST 2015
Fri Jul 10 23:25:16 EEST 2015
// теперь это действительно клоны
Fri Jul 10 23:25:16 EEST 2015
Tue Jul 10 23:25:16 EET 1900
Почему JVM само не может выполнить глубокое клонирование? - Потому как JVM не в курсе насколько клонирование должно быть глубоким:) И как правильно нужно копировать поля, со всеми нюансами, которые задумал программист:)
ИМХО: интерфейс маркер Cloneable обязателен, чтоб можно было понять, переопределен ли метод clone в класса или нет.
TestClone с = new TestClone();
if (с instanceof Cloneable) {
System.out.println("ок, меня можно клонировать");
}
PS
Есть готовое решение от google для глубокого клонирование.
Отличная статья:
Глубокое клонирование в Java без велосипедов