Salinan dalam (salinan dalam) dan salinan dangkal (salinan dangkal) adalah dua konsep yang relatif umum, terutama dalam bahasa C++. Jika Anda tidak memahaminya, Anda akan mengalami masalah saat menghapus, tetapi untungnya kami menggunakan Java di sini. Meskipun Java secara otomatis mengatur daur ulang objek, kita tetap harus memberikan perhatian yang cukup pada salinan dalam (deep copy) dan salinan dangkal (shallow copy), karena terkadang kedua konsep ini sering membawa kita banyak kebingungan.
Salinan dangkal berarti ketika menyalin suatu objek, hanya objek itu sendiri (termasuk variabel dasar dalam objek tersebut) yang disalin, tetapi objek yang ditunjuk oleh referensi yang terdapat dalam objek tersebut tidak disalin. Salinan dalam tidak hanya menyalin objek itu sendiri, tetapi juga menyalin semua objek yang ditunjuk oleh referensi yang terdapat dalam objek tersebut. Misalnya, agar lebih jelas: objek A1 berisi referensi ke B1, dan B1 berisi referensi ke C1. Salinan dangkal A1 untuk mendapatkan A2. A2 masih berisi referensi ke B1, dan B1 masih berisi referensi ke C1. Salinan dalam adalah rekursi dari salinan dangkal. Salinan dalam A1 untuk mendapatkan A2 berisi referensi ke B2 (salinan B1), dan B2 berisi referensi ke C2 (salinan C1).
Jika metode clone() tidak ditulis ulang, objek yang diperoleh dengan memanggil metode ini adalah salinan dangkal. Mari fokus pada salinan mendalam di bawah.
Jalankan program berikut untuk melihat salinan dangkal:
class Professor0 mengimplementasikan Cloneable { String name; int age; class Student0 mengimplementasikan Cloneable { Nama string; // Objek konstan. int age; Professor0 p;//Nilai acuan siswa 1 dan siswa 2 sama. Student0(String nama, int umur, Professor0 p) { this.name = name; this.age = age; this.p = p; } public Object clone() { Student0 o = null; .clone(); } catch (CloneNotSupportedException e) { System.out.println(e.toString()); kembali o; } kelas publik ShallowCopy { public static void main(String[] args) { Profesor0 p = Profesor0 baru("wangwu", 50); Siswa0 s1 = Siswa baru0("zhangsan", 18, p); Siswa0 s2 = (Siswa0) s1.clone(); p.nama = "lisi"; s2.p.umur = 30; s2.nama = "z"; System.out.println("Nama mahasiswa s1 :" + s1.nama + "/n Nama dosen mahasiswa s1 :" + s1.p.nama + "," + "/n Umur dosen mahasiswa s1" + s1 .p.age);//Profesor mahasiswa 1} }
s2 telah berubah, tetapi s1 juga berubah, membuktikan bahwa p dari s1 dan p dari s2 menunjuk ke objek yang sama. Ini tidak terjadi dalam kebutuhan kita yang sebenarnya, jadi kita memerlukan salinan yang mendalam:
class Professor mengimplementasikan Cloneable { String name; int age; clone(); } catch (CloneNotSupportedException e) { System.out.println(e.toString() } return o } } class Siswa mengimplementasikan Cloneable { Nama string; int umur; Profesor p; Mahasiswa(String nama, int umur, Profesor p) { this.name = nama; this.age = age; this.p = p; o = (Mahasiswa) super.clone(); } catch (CloneNotSupportedException e) { System.out.println(e.toString()); p.clone(); kembali o; } } public class DeepCopy { public static void main(String args[]) { long t1 = System.currentTimeMillis(); = Siswa baru("zhangsan", 18, p); Siswa s2 = (Siswa) s1.clone(); s2.p.age = 30; System.out.println("name=" + s1.p.name + "," + "age=" + s1.p.age); // Profesor Siswa 1 tidak berubah. panjang t2 = Sistem.currentTimeMillis(); Sistem.keluar.println(t2-t1);
Tentu saja, kami juga memiliki metode penyalinan mendalam, yaitu membuat serialisasi objek:
import java.io.*; //Serialisasi memakan waktu class Professor2 mengimplementasikan Serializable { /** * */ private static final long serialVersionUID = 1L String name; int age; name = name; this.age = age; } } class Student2 mengimplementasikan Serializable { /** * */ private static final long serialVersionUID = 1L; objek konstan. int age; Profesor2 p;//Nilai acuan siswa 1 dan siswa 2 adalah sama. Student2(String name, int age, Professor2 p) { this.name = name; this.age = age; this.p = p; } public Object deepClone() melempar IOException, OptionalDataException, ClassNotFoundException { // Tulis objek ke aliran Dalam ByteArrayOutputStream bo = ByteArrayOutputStream(); ObjectOutputStream baru oo = ObjectOutputStream(bo); oo.writeObject(ini); // Baca ByteArrayInputStream dari aliran bi = new ByteArrayInputStream(bo.toByteArray()); /** * @param args */ public static void main(String[] args) melempar OptionalDataException, IOException, ClassNotFoundException { panjang t1 = System.currentTimeMillis(); Profesor2 p = Profesor2 baru("wangwu", 50); (); s2.p.nama = "lisi"; s2.p.usia = 30; System.out.println("name=" + s1.p.name + "," + "age=" + s1.p.age); // Profesor Siswa 1 tidak berubah. panjang t2 = Sistem.currentTimeMillis(); Sistem.keluar.println(t2-t1);
Namun, serialisasi sangat memakan waktu. Dalam beberapa kerangka kerja, kita dapat merasakan bahwa mereka sering membuat serialisasi objek dan kemudian mentransfernya, yang memakan banyak waktu.