Вы можете реализовать интерфейс Cloneable
и метод clone()
следующим образом
@Override
public Type clone() {
try {
return (Type) super.clone();
} catch (CloneNotSupporedException cnse) {
throw new RuntimeException(cnse); // Never happens.
}
}
Если вы используете clone()
для более сложных классовВам необходимо убедиться, что все изменяемые объекты, на которые ссылаются поля класса, также рекурсивно клонируются, то есть, что вы делаете глубокую копию вместо мелкой копии.Случайное совместное использование состояния, которое может произойти в результате мелкого копирования, может привести к проблемам, которые трудно отладить.
Использование clone()
имеет ряд проблем.Он обходит конструкторы, которые обычно являются местом, где применяются начальные инварианты класса.Это очень подвержено ошибкам для классов, содержащих больше, чем просто примитивные типы.Кроме того, использование clone()
несовместимо с не примитивными конечными полями, поскольку вы не можете исправить их после клонирования объекта в случае, если они требуют модификации для обеспечения глубокого копирования.
Рассмотрим, например, этот класс:
public class Car {
private final Engine engine;
// ...
@Override
public Car clone() {
try {
Type copy = (Type) super.clone();
copy.engine = (Engine) engine.clone(); // Error: final field cannot be modified.
return copy;
} catch (CloneNotSupportedException cnse) {
throw new RuntimeException(cnse);
}
}
}
Копировать конструкторы, подобные тому, который был опубликован в вопросе, гораздо лучше.