我们在遇到一些业务场景的时候经常需要对对象进行复制,对于对象的复制一般有两种方式,深复制和浅复制
浅复制:对象的复制仅是对象本身,对象引用的其它对方并不会复制。
深复制:对象的复制包含对象引用的对象。
Java所有对象的基类提供了clone方法,但是这个方法是protected native修饰,因此只暴露给之类去重写,外部是无法直接调用的。
我们现在来测试两种复制,首选是浅复制,浅复制要实现Cloneable接口。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
// 课程对象 class Class { private String name; public String getName() { return name; } public void setName(String name) { this .name = name; } } // 学生对象 class User implements Cloneable { private String name; private Long id; // 课程引用 private Class c; public Class getC() { return c; } public void setC(Class c) { this .c = c; } public String getName() { return name; } public void setName(String name) { this .name = name; } public Long getId() { return id; } public void setId(Long id) { this .id = id; } @Override protected Object clone() throws CloneNotSupportedException { return super .clone(); } @Override public int hashCode() { return super .hashCode(); } @Override public boolean equals(Object obj) { if (obj instanceof User) { User user = (User) obj; if ( this .id == user.getId() && this .getName() == user.getName()) { return true ; } if (user.getId().equals( this .id) && user.getName().equals( this .name)) { return true ; } return false ; } else return false ; } } |
我们来测试:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
User user1 = new User(); User user2 = user1; User user3 = (User) user1.clone(); System.out.println(user1 == user2); System.out.println(user3 == user1); System.out.println(user3.equals(user1)); System.out.println(user3.getName() == user3.getName()); // true,浅复制 Class c = new Class(); c.setName( "语文" ); user1.setC(c); // 测试复制深度 User user4 = (User) user1.clone(); System.out.println(user4.getC() == user1.getC()); // true,说明引用的对象依然是同一个对象 |
对象的复制并没复制引用所指向的对象class,复制出来的引用指向的同一个地址。
深复制采用序列化与反序列的方式去获取,也有种说法类似于腌菜,用流的方式腌制进去又取出来,实现深度复制。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
class Car implements Serializable { /** * */ private static final long serialVersionUID = 42342L; private String name; public String getName() { return name; } public void setName(String name) { this .name = name; } } // 深复制 class People implements Serializable{ /** * */ private static final long serialVersionUID = 543535212412L; private Car car; public Car getCar() { return car; } public void setCar(Car car) { this .car = car; } public People deepClone() throws IOException, ClassNotFoundException { // 腌制 ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(out); oos.writeObject( this ); // 取出 ByteArrayInputStream input = new ByteArrayInputStream(out.toByteArray()); ObjectInputStream ois = new ObjectInputStream(input); return (People) ois.readObject(); } } |
测试深复制:
1
2
3
4
5
6
7
8
9
10
11
12
|
// 深复制 Car car = new Car(); car.setName( "benz" ); People p = new People(); p.setCar(car); try { People p2 = p.deepClone(); System.out.println(p2.getCar() == p.getCar()); // false,说明引用的对象也进行了复制 } catch (ClassNotFoundException | IOException e) { e.printStackTrace(); } |
例外提及一下生成对象的五种办法:
1.new
2.Class类的newInstance
3.Constructor类newInstance
4.Clone方式
5.反序列化的方式
其中2与3即是反射的方式。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
原文链接:http://blog.csdn.net/micro_hz/article/details/54576281