Прежде чем официально ввести тему, давайте впервые поймем концепции глубокой копии и предварительной копии:
Светлая копия:
Будет создан новый объект, который имеет точную копию значения свойства исходного объекта. Если атрибут является основным типом, значение базового типа копируется; Если атрибут является адресом памяти, адрес памяти копируется, поэтому, если объект изменит этот адрес, это повлияет на другой объект;
Глубокая копия:
Вы не только хотите скопировать все значения переменных элементов, не приведенных на реферат объекта, но вам также необходимо создать новый экземпляр для переменных членов типа ссылки и инициализировать его до значения экземпляра формального параметра;
После понимания концепции давайте проверим, являются ли обычные операции по назначению объектов глубокой копией или неглубокой копии:
Тестовый код:
открытый класс Debincopy {public static void main (string [] args) {copy First = new Copy ("hzw", 24); Копировать второе = первое; second.name = "shanxi"; System.out.println (first.name); // Выход Shanxi}} class Copy {public String name; Public Int Age; public copy (string name, int age) {this.name = name; this.age = возраст; }} Можно обнаружить, что после второго изменения значения атрибута имени на Shanxi значение атрибута имени также становится Shanxi. Это показывает, что обычные назначения объектов принадлежат мелким копиям;
После понимания того, является ли назначение между объектами мелкой копией, давайте посмотрим, является ли клонирование глубокой копией или мелкой копией. Тестовый код состоит в том, чтобы включить вышеуказанный объект копирования для реализации метода клона в клонируемом интерфейсе:
открытый класс Debincopy {public static void main (string [] args) {copy First = new Copy ("hzw", 24); Копировать второе = null; try {second = (copy) first.clone (); } catch (clonenotsupportedException e) {e.printstacktrace (); } second.name = "shanxi"; System.out.println(first.name);//Output: hzw System.out.println(first);//Output: com.hzw.day33.Copy@7f39ebdb System.out.println(second);//Output: com.hzw.day33.Copy@33abb81e } } class Copy implements Cloneable { public String name; Public Int Age; public copy (string name, int age) {this.name = name; this.age = возраст; } @Override Protected Object Clone () бросает ClonenotSupportedException {return super.clone (); }}Можно видеть, что первоначально созданный объект сначала и клонированный объект вторым - это два экземпляра, поэтому изменение атрибута имени во втором не повлияет на атрибут имени в первую очередь; Однако мы не можем просто думать, что клонирование - это глубокая копия, например, следующий пример:
Общедоступный класс Debincopy {public static void main (string [] args) {Студент Студент = новый студент (95); Копировать первый = новая копия ("hzw", 24, студент); Копировать второе = null; try {second = (copy) first.clone (); } catch (clonenotsupportedException e) {e.printstacktrace (); } second.name = "shanxi"; Second.Student.Score = 60; System.out.println (First == Second); // false System.out.println (first.student == second.student); // true system.out.out.println (first.student.score); // 60}} класс копировать внедрение {public String name; Public Int Age; государственный студент; public Copy (String name, int Age, студент -студент) {this.name = name; this.age = возраст; this.student = студент; } @Override Protected Object Clone () бросает ClonenotSupportedException {return super.clone (); }} класс Студент {public int comp; public Student (int chpold) {this.score = scord; }}Ты это видел? Мы создали второе место через клонирование, и очевидно, что первым и вторым - два экземпляра, потому что результат первого == секунду является ложным, но студент объектов в первом и втором. После изменения значения оценки студента через второе место, оценка студента в первом также изменилась. Это означает, что студент в первом и втором - это то же самое. Это означает, что клонирование является мелкой копией. Если мы хотим внедрить глубокую копию клонирования, мы должны позволить объекту студента в объекте копирования также реализовать метод клона в клонируемом интерфейсе, а метод клона в копии возвращает клон студента, чтобы студент мог быть уникальным. Модифицированный код заключается в следующем:
Общедоступный класс Debincopy {public static void main (string [] args) {Студент Студент = новый студент (95); Копировать первый = новая копия ("hzw", 24, студент); Копировать второе = null; try {second = (copy) first.clone (); } catch (clonenotsupportedException e) {e.printstacktrace (); } second.name = "shanxi"; Second.Student.Score = 60; System.out.println (First == Second); // false System.out.println (first.student == second.student); // false system.out.println (first.student.score); // 95 System.out.println (second.student.score); // 60}} класс Completive Comples Clonable {virew String name; // 60}} compess compree completiples clonable {virew name; Public Int Age; государственный студент; public Copy (String name, int Age, студент -студент) {this.name = name; this.age = возраст; this.student = студент; } @Override Protected Object Clone () Throws CloneNotSupportedException {copy Copy = (copy) super.clone (); copy.student = (студент) студент.clone (); вернуть копию; }} класс Студент реализует клонируемые {public int score; public Student (int chpold) {this.score = scord; } @Override Protected Object Clone () бросает ClonenotSupportedException {return super.clone (); }} Вы можете увидеть это первым и вторым, первым. Студент и второй. Студент не совпадает в настоящее время. Поэтому после того, как мы изменим оценку второго студента, это не влияет на стоимость студента в первом, достигая цели глубокого копирования;
Однако, если вы внимательно подумаете об этом, проблема возникнет. Если в нашем примере также есть атрибуты типов ссылок, такие как класс колледжа, то мы должны позволить классу колледжа реализовать клонируемый интерфейс, а затем позвонить в метод клона класса колледжа в методе клонов в классе учеников и вызвать метод клона класса учеников в методе клонов класса копирования. Я обнаружил, что это исчезло. Этот процесс настолько сложный. Все соответствующие типы ссылок в классе должны реализовать клонируемый интерфейс. Я чувствую, что это так хлопотно, хорошо, следующее - быть потрясающим.
Лучший способ решить проблему с глубокой копией - это использовать сериализацию, чтобы все классы не должны были реализовать клонируемый интерфейс, просто сериализовать и десериализовать напрямую. Давайте посмотрим.
Импорт java.io.file; импортировать java.io.fileinputstream; Импорт java.io.fileOutputStream; импортировать java.io.objectinputstream; Импорт java.io.objectOutputStream; импортировать java.io.serializable; Общедоступный класс Debincopy {public static void main (string [] args) {Колледж Школа = новый колледж ("nongda"); Студент = новый ученик (95, школа); Копирование копирования = новая копия ("hzw", 23, студент); Скопировать другой = null; // Укажите десериализованный экземпляр класса // сериализовать операцию сериализации try {fileOutputStream fos = new FileOutputStream (новый файл ("d: /copy.txt")); ObjectOutputStream oos = new ObjectOutputStream (FOS); oos.writeObject (копия); } catch (Exception e) {e.printstackTrace (); } // сериализуйте операцию десериализации FileInputStream FIS; try {fis = new FileInputStream (новый файл ("d: /copy.txt")); ObjectInputStream OIS = new ObjectInputStream (FIS); другой = (копия) OIS.ReadObject (); } catch (Exception e) {e.printstackTrace (); } System.out.println (copy == ore); // false System.out.println (copy.student == oremon.student); // false system.out.println (copy.student.school == rother.student.school); // false student.school = "wuda"; System.out.println (copy.student.school.schoolname); // nongda}} класс копирование реализует сериализуемые {public String name; Public Int Age; государственный студент; public Copy (String name, int Age, студент -студент) {this.name = name; this.age = возраст; this.student = студент; }} класс Студент реализует Serializable {public int стержень; Школа государственного колледжа; Public Student (int Score, школа колледжа) {this.score = счет; this.school = школа; }} класс колледж реализует serializable {public String SchoolName; Public College (String SchoolName) {this.schoolname = SchoolName; }} Из вывода мы видим, что объект, сгенерированный после десериализации, является копией исходного объекта, и он не имеет никаких отношений с исходным объектом, за исключением того же значения атрибута. Поэтому, когда мы модифицируем имя школьного маршрута, сгенерированного объектом, чтобы «wuda», мы не изменяли имя школьного анализа исходного экземпляра, и мы все еще выводим «nongda», поэтому мы достигли настоящего глубокого эффекта копии. Однако для достижения сериализации все соответствующие классы должны реализовать сериализуемый интерфейс, который всегда более удобен, чем реализация как клонируемый интерфейс, так и метод клона.
Выше приведено подробное объяснение глубоких и мелких копий Java. Если вам это нужно, пожалуйста, обратитесь к этому.