Переопределение метода Clone () в Java, когда суперкласс не Clonable - PullRequest
1 голос
/ 26 января 2020

Как клонировать объект Java с помощью метода clone ()

У меня есть вопрос относительно правильной реализации метода clone() для класса в java. Я знаю, что это плохая практика, но мне нужно знать это для экзамена. В вышеупомянутом обсуждении говорят, что нужно вызвать super.clone() - но я не понимаю, что произойдет, если суперфункция не реализует Clonable. Например, скажем, у меня есть класс X, расширяющий Y. X реализует Clonable, а Y - нет. Метод Y's clone() должен выдавать исключение. Тогда что мы будем делать в этом случае?

Все объяснения, которые я смог найти, как-то предполагают, что все суперклассы реализуют Clonable, или, по крайней мере, это то, что я понял ..

РЕДАКТИРОВАТЬ:

Проверьте этот код, пожалуйста:

public class Employee implements Cloneable {

private String name;

public Employee(String name) {
    this.name = name;
}

public String getName() {
    return name;
}

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

public static void main(String[] args) {
    Employee emp = new Employee("Abhi");
    try {
        Employee emp2 = (Employee) emp.clone();
        System.out.println(emp2.getName());
    } catch (CloneNotSupportedException e) {
        e.printStackTrace();
    }
}

}

Он взят здесь: https://www.javacodegeeks.com/2018/03/understanding-cloneable-interface-in-java.html

Подобный код можно найти во многих руководствах.

Почему они могут использовать super.clone(), когда суперкласс (в данном случае Object) не реализует Clonable - это приведет к исключению.

Ответы [ 2 ]

2 голосов
/ 26 января 2020

Если у вас есть такая структура:

class Y {}

class X extends Y implements Cloneable {
    @Override
    public X clone() {
        try {
            return (X) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e);
        } 
    }
}

Тогда клон на экземплярах X будет работать нормально. Он не будет работать на прямых экземплярах Y, потому что они не объявлены клонируемыми. Но интерфейс Cloneable в X является индикатором механизмов реализации по умолчанию clone(), что их следует заставить работать.

В качестве альтернативы

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

Например:

class Y {
    @Override
    public Y clone() {
        // Don't call super.clone() because it will error
        return new Y(...); // whatever parameters
    }
}

Однако, с помощью этого механизма, если вы вызываете super.clone() из подкласса Y, вы получите экземпляр Y, что, вероятно, не то, что вы хотели бы.

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

1 голос
/ 26 января 2020

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

Я бы не рекомендовал использовать его вообще. Лучшим решением было бы предоставить copy-constructors . Если у человека нет возможности полностью воссоздать объект родительского класса, клонирование невозможно.

Рефакторинг предоставленного кода приведет к результату, подобному следующему:

public class Employee implements Cloneable {

    private String name;

    public Employee(String name) {
        this.name = name;
    }

    public Employee(Employee that) {
        this.name = that.name;
    }

    public static void main(String[] args) {
        Employee emp = new Employee("Abhi");
        Employee emp2 = new Employee(emp);
        System.out.println(emp2.getName());
    }

    public String getName() {
        return name;
    }
}

Замечание к вашему коду:

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

Приведение типов излишне, так как метод возвращает Object.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...