Глубокое копирование (глубокое копирование) и поверхностное копирование (мелкое копирование) — две относительно распространенные концепции, особенно в языке C++. Если вы этого не понимаете, у вас возникнут проблемы при удалении, но, к счастью, здесь мы используем Java. Хотя Java автоматически управляет переработкой объектов, нам все равно приходится уделять достаточно внимания глубокому копированию (deep copy) и мелкому копированию (shallow copy), поскольку иногда эти два понятия часто приносят нам большую путаницу.
Неглубокое копирование означает, что при копировании объекта копируется только сам объект (включая основные переменные в объекте), но объект, на который указывает ссылка, содержащаяся в объекте, не копируется. Глубокая копия не только копирует сам объект, но также копирует все объекты, на которые указывают ссылки, содержащиеся в объекте. Например, чтобы было понятнее: объект A1 содержит ссылку на B1, а B1 содержит ссылку на C1. Неглубокое копирование A1 для получения A2. A2 по-прежнему содержит ссылку на B1, а B1 по-прежнему содержит ссылку на C1. Глубокая копия — это рекурсия поверхностной копии A1 для получения A2. A2 содержит ссылку на B2 (копию B1), а B2 содержит ссылку на C2 (копию C1).
Если метод clone() не переписан, объект, полученный в результате вызова этого метода, является поверхностной копией. Ниже мы сосредоточимся на глубокой копии.
Запустите следующую программу, чтобы просмотреть поверхностную копию:
класс Professor0 реализует Cloneable { String name; int age; String name, int age) { this.name = name; this.age = age; } public Object clone() бросает CloneNotSupportedException { return super.clone() } ; класс Student0 реализует Cloneable { String name // Constant object; int age; Professor0 p;//Опорные значения студента 1 и студента 2 одинаковы. Student0(String name, int age, Professor0 p) { this.name = name; this.age = age; this.p = p; } public Object clone() { Student0 o = try { o = (Student0) super .clone(); } catch (CloneNotSupportedException e) { System.out.println(e.toString()} return o; } } public class ShallowCopy { public static void); main(String[] args) { Professor0 p = новый Professor0("wangwu", 50); Student0 s1 = новый Student0("zhangsan", 18, p); Student0 s2 = (Student0) s1.clone(); p.name = "lisi"; s2.p.age = 30; s2.name = "z"; System.out.println("Имя студента s1:" + s1.name + "/n Имя профессора студента s1:" + s1.p.name + "," + "/n Возраст профессора студента s1" + s1 .p.age);//Профессор студента 1} }
s2 изменился, но изменился и s1, доказывая, что p из s1 и p из s2 указывают на один и тот же объект. В наших реальных целях это не так, поэтому нам нужна глубокая копия:
класс Профессор реализует Cloneable {String name; int age; String name, int age) { this.name = name; this.age = age } public Object clone () { Object o = null; clone(); } catch (CloneNotSupportedException e) { System.out.println(e.toString()) return o; } } Класс Student реализует Cloneable { String name; int age; Student(String name, int age, Professor p) { this.name = name; this.age = age; this.p = p; } public Object clone() { Student o = null; о = (Студент) super.clone(); } catch (CloneNotSupportedException e) { System.out.println(e.toString()); op = (Профессор) p.clone(); return o; } } public class DeepCopy { public static void main(String args[]) { long t1 = System.currentTimeMillis(); новый профессор("wangwu", 50); = новый Студент("Чжансан", 18, п); Студент s2 = (Студент) s1.clone(); s2.p.name = "lisi"; s2.p.age = 30; System.out.println("name=" + s1.p.name + "," + "age=" + s1.p.age); // Профессор студента 1 не меняется. длинный t2 = System.currentTimeMillis() System.out.println(t2-t1);
Конечно, у нас также есть метод глубокого копирования, который сериализует объект:
import java.io.*; // Сериализация требует много времени. Класс Professor2 реализует Serializable { /** * */ Private static Final long SerialVersionUID = 1L; int age; String name, int age) { this. name = name; this.age = age; } } класс Student2 реализует Serializable { /** * */ Private static Final long SerialVersionUID = 1L String name;// постоянный объект. int age; Professor2 p;//Опорные значения студента 1 и студента 2 одинаковы. Student2(String name, int age, Professor2 p) { this.name = name; this.age = age; this.p = p; } public Object deepClone() бросает IOException,OptionalDataException, ClassNotFoundException { // Записываем объект в поток в ByteArrayOutputStream bo = новый ByteArrayOutputStream () ObjectOutputStream oo = новый ObjectOutputStream (бо); oo.writeObject(this); // Чтение ByteArrayInputStream из потока bi = new ByteArrayInputStream(bo.toByteArray()); ObjectInputStream oi = new ObjectInputStream(bi); return (oi.readObject()); /** * @param args */ public static void main(String[] args) выбрасываетOptionalDataException, IOException, ClassNotFoundException { long t1 = System.currentTimeMillis(); (); s2.p.name = "lisi"; s2.p.age = 30; System.out.println("name=" + s1.p.name + "," + "age=" + s1.p.age); // Профессор студента 1 не меняется. long t2 = System.currentTimeMillis() System.out.println(t2-t1);
Однако сериализация занимает очень много времени. В некоторых фреймворках мы можем почувствовать, что они часто сериализуют объекты, а затем передают их, что занимает много времени.