it-roy-ru.com

какой смысл позволять моему классу реализовывать Cloneable?

Я наткнулся на некоторый код класса, который реализует Clonable, в документации говорится:

Класс реализует интерфейс Cloneable, чтобы указать методу Object.clone (), что для этого метода допустимо делать копию поля для поля экземпляров этого класса . Вызов метода clone объекта в экземпляре, который не реализует интерфейс Cloneable, приводит к исключению CloneNotSupportedException . По соглашению классы, которые реализуют этот интерфейс, должны переопределить Object.clone (который защищен) с помощью открытого метода. Смотрите Object.clone () для подробностей о переопределении этого метода . Обратите внимание, что этот интерфейс не содержит метод клонирования. Следовательно, невозможно клонировать объект только в силу того факта, что он реализует этот интерфейс. Даже если метод клона вызывается рефлексивно, нет никаких гарантий, что он будет успешным.

Я не могу понять смысл реализации этого класса, как сказано в документации, метод .clone не реализован в интерфейсе, и я должен реализовать его. Так зачем использовать этот класс? Почему я не могу просто написать метод copyClass в моем классе, чтобы сделать копию объекта без реализации этого класса?

Заранее спасибо.

17
Emil Adz

Чтобы реализовать метод клонирования, вы просто делаете:

public Object clone() throws CloneNotSupportedException {
    return super.clone();
}

Конечно, вы можете настроить метод, чтобы сделать более глубокую копию, если это необходимо.

Вызов super.clone() почти обязателен, потому что, если класс не является окончательным и, следовательно, не может быть переопределен, метод clone() должен возвращать экземпляр того же класса, что и объект, для которого он вызван. Поэтому простое создание нового экземпляра и копирование состояния будет работать для этого класса, но не для всех подклассов. Более того, вы не всегда имеете доступ ко всем состояниям, содержащимся в суперклассах.

Короче говоря, вы делаете публично защищенный метод клонирования Object. И первое, что делает метод Object.clone() (это не реальный код, но то, что делает метод):

if (!(this instanceof Cloneable)) {
    throw new CloneNotSupportedException();
}

Итак, Cloneable - это просто интерфейс маркера, позволяющий методу Object.clone() знать, что он не должен вызывать исключение при вызове.

Это одна из самых плохо спроектированных частей Java. Обычно вы предпочитаете использовать конструктор копирования вместо использования clone().

25
JB Nizet

Это позволяет вам писать более общий код. Если у вас есть несколько классов, реализующих интерфейс Cloneable, и вы хотите передать их экземпляры в качестве аргумента методу, вам не нужно создавать несколько методов, отличающихся одним типом переменной, вы можете просто использовать Cloneable t. То же самое с другими интерфейсами. И то же самое с любым другим интерфейсом, это своего рода множественное наследование. Реализация этих интерфейсов делает ваш код более разборчивым.

1
Mateusz