Deep copy (deep copy) and shallow copy (shallow copy) are two more general concepts, especially in the C + + language, which can be problematic when the delete is not understood, but we are fortunately using Java in this case. While Java automatically manages the recycling of objects, we pay enough attention to deep copy (deep copy) and shallow copy (shallow copy), because sometimes these two concepts often bring us no small confusion.
a shallow copy is a copy of an object that simply copies the object itself (including the underlying variable in the object), without copying the object that the object contains a reference to. A deep copy not only copies the object itself, but also copies all objects that the object contains to which the reference points. For example, it is more clear that the object A1 contains a reference to B1, and B1 contains a reference to C1. Shallow copy A1 The A2,A2 still contains a reference to B1, and B1 still contains a reference to C1. The deep copy is recursive to the shallow copy, and the deep copy A1 gets a reference to the B2 (B1 copy) contained in the A2,A2, and B2 contains a reference to C2 (C1 copy).
If the Clone () method is not overwritten, the object called by this method is a shallow copy, and we'll focus on the deep copy below.
Run the following program and take a look at the shallow copy:
class
Professor0 implements
Cloneable { //实现Cloneable接口,将clone重定义为public,Cloneable只是标记接口,没有具体方法,唯一目的就是用instanceof进行类型检查
String name;
int
age;
Professor0(String name, int
age) {
this
.name = name;
this
.age = age;
}
public Object clone() throws CloneNotSupportedException { return super .clone();
}
}
class
Student0 implements
Cloneable {
String name;
// 常量对象。
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 = null
;
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 = new
Professor0(
"wangwu"
, 50
);
Student0 s1 = new Student0(
"zhangsan"
, 18
, p);
Student0 s2 = (Student0) s1.clone();
s2.p.name = "lisi"
;
s2.p.age = 30
;
s2.name = "z"
;
s2.age = 45
;
System.out.println(
"学生s1的姓名:"
+ s1.name + "\n学生s1教授的姓名:"
+ s1.p.name + ","
+ "\n学生s1教授的年纪"
+ s1.p.age);
// 学生1的教授
}
}
|
S2 changed, but S1 also changed, proving that S1 p and S2 p point to the same object. This is not the case in our actual needs, so we need a deep copy:
class
Professor implements
Cloneable {
String name;
int
age;
Professor(String name, int
age) {
this
.name = name;
this
.age = age;
}
public
Object clone() {
Object o = null
;
try
{
o = super
.clone();
} catch
(CloneNotSupportedException e) {
System.out.println(e.toString());
}
return
o;
}
}
class
Student implements
Cloneable {
String name;
int
age;
Professor p;
Student(String name, int
age, Professor p) {
this
.name = name;
this
.age = age;
this
.p = p;
}
public
Object clone() {
Student o = null
;
try
{
o = (Student) super
.clone();
} catch
(CloneNotSupportedException e) {
System.out.println(e.toString());
}
o.p = (Professor) p.clone();
return o;
}
}
public
class
DeepCopy {
public
static
void
main(String args[]) {
long
t1 = System.currentTimeMillis();
Professor p = new
Professor(
"wangwu"
, 50
);
Student s1 = new
Student(
"zhangsan"
, 18
, p);
Student s2 = (Student) s1.clone();
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);
}
}
|
Of course we also have a deep copy method, which is to serialize the object:
import
java.io.*;
//Serialization is time-consuming
class Professor2 implements
Serializable {
private
static
final
long
serialVersionUID = 1L;
String name;
int
age;
Professor2(String name, int
age) {
this
.name = name;
this
.age = age;
}
}
class
Student2 implements
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() throws
IOException, OptionalDataException,
ClassNotFoundException {
// 将对象写到流里
ByteArrayOutputStream bo = new
ByteArrayOutputStream();
ObjectOutputStream oo = new
ObjectOutputStream(bo);
oo.writeObject(
this
);
// 从流里读出来
ByteArrayInputStream bi = new
ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi = new
ObjectInputStream(bi);
return
(oi.readObject());
}
}
public
class
DeepCopy2 {
/**
* @param args
*/
public
static
void
main(String[] args) throws
OptionalDataException,
IOException, ClassNotFoundException {
long
t1 = System.currentTimeMillis();
Professor2 p = new
Professor2(
"wangwu"
, 50
);
Student2 s1 = new
Student2(
"zhangsan"
, 18
, p);
Student2 s2 = (Student2) s1.deepClone();
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);
}
}
|
But serialization is time-consuming, and in some frameworks, we can feel that they tend to serialize objects and pass them around, and it takes more time.
Deep copy (deep copy) and shallow copy (shallow copy) in Java