У меня есть код, который выполняет глубокую копию с использованием Object.clone, но я пытаюсь переписать его, используя более «приемлемую» конструкцию конструктора экземпляра. Ниже приведены два простых примера того, что я пытаюсь сделать, первый из которых использует клон, а второй - конструктор копирования.Правильный способ глубокой копии с помощью конструктора копирования вместо Object.clone
Deep копия с использованием клона
import java.util.*;
abstract class Person implements Cloneable {
String name;
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Teacher extends Person implements Cloneable {
int courses;
public String toString() { return name + ": courses=" + courses; }
}
class Student extends Person implements Cloneable {
double gpa;
public String toString() { return name + ": gpa=" + gpa; }
}
public class DeepCopy_Clone {
private static List<Person> deepCopy(List<Person> people) throws CloneNotSupportedException {
List<Person> copy = new ArrayList<Person>();
for (Person person : people) {
copy.add((Person)person.clone());
}
return copy;
}
public static void main(String[] args) throws CloneNotSupportedException {
ArrayList<Person> people = new ArrayList<Person>();
Teacher teacher = new Teacher();
teacher.name = "Teacher";
teacher.courses = 5;
people.add(teacher);
Student student = new Student();
student.name = "Student";
student.gpa = 4.0;
people.add(student);
List<Person> peopleCopy = deepCopy(people);
// Invalidate the original data to prove a deep copy occurred
teacher.name = null;
teacher.courses = -1;
student.name = null;
student.gpa = -1;
for (Person person : peopleCopy) {
System.out.println(person.toString());
}
}
}
Deep копия с использованием конструктор копирования
import java.util.*;
abstract class Person {
String name;
public Person() {}
public Person(Person other) {
this.name = other.name;
}
public Person deepCopy() {
if (this instanceof Teacher) {
return new Teacher((Teacher)this);
} else if (this instanceof Student) {
return new Student((Student)this);
}
throw new Error("Unknown type of person");
}
}
class Teacher extends Person {
int courses;
public Teacher() {}
public Teacher(Teacher other) {
super(other);
this.courses = other.courses;
}
public String toString() { return name + ": courses=" + courses; }
}
class Student extends Person {
double gpa;
public Student() {}
public Student(Student other) {
super(other);
this.gpa = other.gpa;
}
public String toString() { return name + ": gpa=" + gpa; }
}
public class DeepCopy_ConstructorAlternative {
private static List<Person> deepCopy(List<Person> people) {
List<Person> copy = new ArrayList<Person>();
for (Person person : people) {
copy.add(person.deepCopy());
}
return copy;
}
public static void main(String[] args) {
ArrayList<Person> people = new ArrayList<Person>();
Teacher teacher = new Teacher();
teacher.name = "Teacher";
teacher.courses = 5;
people.add(teacher);
Student student = new Student();
student.name = "Student";
student.gpa = 4.0;
people.add(student);
List<Person> peopleCopy = deepCopy(people);
// Invalidate the original data to prove a deep copy occurred
teacher.name = null;
teacher.courses = -1;
student.name = null;
student.gpa = -1;
for (Person person : peopleCopy) {
System.out.println(person.toString());
}
}
}
Что я нахожу интересным является то, что, несмотря на все разговоры о вреде клонирования в Яве альтернатива клонов требует меньше кода и меньше бросков (в данном конкретном случае, по крайней мере).
Я буду благодарен за обратную связь по альтернативе конструктора копирования. Не могли бы вы поступить иначе? Благодарю.
Забыть или не удалось обновить Person.deepCopy, не связанные с проблемой. То есть, вы можете столкнуться с очень похожими проблемами с альтернативой клона. Например, если кто-то создает новый «Администратор класса расширяет личность», ему придется не забудьте реализовать Administrator.clone (при условии, что копия по каждому полю не выполняет глубокую копию). Невозможно обновить Person.deepCopy можно обработать, переопределив его в подклассе. И да, вы должны помнить об этом, но опять же это проблема с альтернативой клона. – vocaro