2010-05-22 2 views
2

Java-документации говорит:Вопрос о Cloneable интерфейса и исключения, которые должны быть брошенной

класс реализует интерфейс Cloneable для указания метода Object.clone(), что является законным для этот способ сделать поле для копирования экземпляров этого класса. Метод клона

ссылающегося объекта на экземпляре, который не реализует Cloneable результатов интерфейса в исключения CloneNotSupportedException бросок.

По соглашению, классы, которые реализуют этот интерфейс должен переопределить Object.clone (защищенный) с публичным методом. Дополнительную информацию об переопределении этого метода см. В Object.clone() .

Обратите внимание, что этот интерфейс не содержит , содержащий метод клонирования. Поэтому невозможно клонировать объект только в силу того, что он реализует этот интерфейс. Даже если метод clone вызывает рефлексивно, нет гарантии, что он достигнет .

И у меня есть этот UserProfile класс:

public class UserProfile implements Cloneable { 
    private String name; 
    private int ssn; 
    private String address; 

    public UserProfile(String name, int ssn, String address) { 
     this.name = name; 
     this.ssn = ssn; 
     this.address = address; 
    } 

    public UserProfile(UserProfile user) { 
     this.name = user.getName(); 
     this.ssn = user.getSSN(); 
     this.address = user.getAddress(); 
    } 

    // get methods here... 

    @Override 
    public UserProfile clone() { 
     return new UserProfile(this); 
    } 
} 

И для тестирования porpuses, я делаю это в main():

UserProfile up1 = new UserProfile("User", 123, "Street"); 
UserProfile up2 = up1.clone(); 

До сих пор никаких проблем с компиляцией/погонный. Теперь, по моему пониманию документации, удаление implements Cloneable из класса UserProfile должно вызвать исключение в вызове up1.clone(), но это не так.

Я читал здесь, что интерфейс Cloneable сломан, но я действительно не знаю, что это значит. Я что-то упускаю?

+1

Cloneable является проблематичным, поскольку Cloneable интерфейс не имеет метода клон(), вам необходимо либо знать конкретный тип, который реализует метод Clone() (в этом случае вам конкретный тип, так что вы вместо этого может использовать конструктор копирования), или вам нужно использовать отражение. Любой API, который требует отражения для правильной работы, может быть описан как сломанный. –

+0

Будьте осторожны: в методе clone не вызывайте конструктор, а вызывайте (UserProfile) super.clone(). См. Http://java.sun.com/javase/6/docs/api/java/lang/Object.html#clone%28%29 «По соглашению ...» – Istao

ответ

5

Теперь, согласно моему пониманию документации, извлекая implements Cloneable из UserProfile класса должен бросить и исключение up1.clone() вызова, но это не так.

Пока ваш класс по-прежнему имеет реализацию метода clone(), исключение будет конечно не будет выброшено, когда вы называете это - он работает так же, как и любой другой метод, нет никакого особого волшебства.

Реализация clone() в классе Object является тем, что вызывает исключение, но вы переопределили этот метод.

+0

По крайней мере, какая-то магия задействована, потому что Object. clone() не будет вызывать это исключение при вызове через super.clone(). Но, кроме этого, я согласен. – Axel

+0

'Object.clone()' проверяет, является ли объект экземпляром класса, который реализует 'Cloneable' и генерирует исключение, если это не так. Никакой специальной магии (например, специальной обработки компилятором) не требуется ... – Jesper

1

Это означает, что если вы реализуете Cloneable и опускаете метод clone(), а THEN вызываете метод clone(), генерируется исключение.

EDIT: Как уже упоминалось, вероятно, 1 миллиард раз прежде, но

НЕ ИСПОЛЬЗОВАТЬ CLONE МЕТОД!

Если вам нужна функция клонирования, укажите вместо этого конструктор копирования.

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

+0

В чем аргумент за то, что вы не используете метод clone, если я переопределяю его своей собственной реализацией? –

+0

IMHO, просто внедряющий конструктор копирования, может привести к другим проблемам в отношении наследования. Я не понимаю, почему нужно быть хуже другого. И в таком случае, почему бы не придерживаться стандартного Cloneable? По крайней мере, большинство разработчиков знают о своих недостатках и могут справиться с ними. – Axel

+0

Насколько я могу это видеть, я переопределяю метод clone в своем классе, и все, что он делает, вызывает конструктор копирования. В чем проблема? –

1

Я согласен с обоими ответами и добавляю что-то: интерфейс подобен «тегу», чтобы сказать, что ваш класс реализует клон(). Это полезно в api-подобных методах, когда вы не знаете тип объекта. Тогда вы можете написать

if (myobj instanceof Cloneable) { dosmthng(); } 
+1

Вы должны использовать 'instanceof' вместо' is'. – Jesper

+0

Исправлено, я смешанные вещи с C#. Благодарю. –

Смежные вопросы