Почему бы не включить внутри переопределенного .clone?
Я понимаю, как работает клонирование Java, и аргументы против его использования. Позволяет сказать, что я все равно мертв, используя его.
Для удобства я хотел бы написать метод clone для класса Foo следующим образом:
@Override
public Foo clone(){
Foo f = (Foo)super.clone();
//Replace mutable fields
return f;
}
Насколько я могу судить, это было бы безопасно. Однако я заметил, что классы Cloneable в API не делают этого. Есть ли причина для этого, и это плохой стиль?
Ответы
Ответ 1
Перед Java 5 ковариантные типы возвращаемых данных вообще не разрешались, поэтому Foo clone()
даже не компилировался.
Поскольку много классов Cloneable
было написано давно, возможно, причина большинства случаев.
Я подозреваю, что новые классы не используют его просто потому, что clone()
, как известно, довольно горст, и когда люди редко его используют, они даже не думают, что могут его использовать. Они находят некоторые "как реализовать запрос clone()" и записывают код по-старому.
Ответ 2
Object.clone()
создает новый объект, где все поля имеют то же значение, что и оригинал. Для полей ссылочного типа это означает, что новое поле является просто ссылкой на тот же объект, что и исходный. Это не поля clone
. Поэтому во многих случаях реализация по умолчанию приведет к совместным данным, что может быть нежелательным. Например, если ArrayList.clone()
использовал реализацию по умолчанию, вы получили бы два экземпляра ArrayList
, имеющих один и тот же массив поддержки.
Если все поля объекта неизменяемы, может быть хорошей идеей просто привести результат super.clone()
к соответствующему типу.
Ответ 3
Хм, это определенно не плохой стиль, на самом деле его предпочтительнее, если вы делаете это с момента выпуска java 1.5, потому что ковариантные типы возврата были
представленный в выпуске 1.5 как часть дженериков, и, делая это, вы упрощаете использование вашего API (никакого литья не потребуется).
source (Эффективное java-издание 2).