1.序列化实现
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 |
public class CloneUtils {
@SuppressWarnings ( "unchecked" ) public static <T extends Serializable> T clone(T object){
T cloneObj = null ; try { ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream obs = new ObjectOutputStream(out); obs.writeObject(object); obs.close();
ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray()); ObjectInputStream ois = new ObjectInputStream(ios); cloneObj = (T) ois.readObject();
} catch (Exception e){ e.printStackTrace(); } return cloneObj;
}
} |
2.主代码
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 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
public class TestString { public static void main(String[] args) { TestString test = new TestString(); System.out.println( "-------浅拷贝---------" ); test.qianCopyTest();
System.out.println();
System.out.println( "--------使用clone深拷贝--------" ); test.defaultCloneTest();
System.out.println();
System.out.println( "--------使用序列化实现对象的拷贝--------" ); test.streamClonrTest();
System.out.println( "--------耗时对比--------" ); System.out.println( "耗时1 : " + test.qianCopyCost()); System.out.println( "耗时2 : " + test.CloneCopyCost()); System.out.println( "耗时3 : " + test.StreamCopyCost()); }
/*浅拷贝*/ private void qianCopyTest() { String s = "cd"; change(s); System.out.println(s); System.out.println("----------------"); String b = new String("cd"); change(b); System.out.println(b); System.out.println("----------------"); int me = 1; change(me); System.out.println(me); System.out.println("----------------"); Person person = new Person("我", 13,new Email("我")); change(person); System.out.println(person.toString()); }
/*使用默认的clone方法,需要Person实现Cloneable接口*/ private void defaultCloneTest(){ Person person = new Person("我", 13,new Email("我")); Person person1 = person.clone(); Person person2 = person.clone(); System.out.println("person : 【"+person+"】"); System.out.println("person1 : 【"+person1+"】"); System.out.println("person2 : 【"+person2+"】"); //改一个就会触动全部!! 这就是使用默认的clone方法的弊端 /*该clone()方法是使用Object类的clone()方法,但是该方法存在一个缺陷,它并不会将对象的所有属性全部拷贝过来,而是有选择性的拷贝,基本规则如下: 1、 基本类型 如果变量是基本很类型,则拷贝其值,比如int、float等。 2、 对象 如果变量是一个实例对象,则拷贝其地址引用,也就是说此时新对象与原来对象是公用该实例变量。 3、 String字符串 若变量为String字符串,则拷贝其地址引用。但是在修改时,它会从字符串池中重新生成一个新的字符串,原有紫都城对象保持不变。*/ person.getEmail().setContent("你"); System.out.println("之后的person : 【"+person+"】"); System.out.println("之后的person1 : 【"+person1+"】"); System.out.println("之后的person2 : 【"+person2+"】"); }
/*使用序列化实现对象的拷贝,需要对象以及对象中的其他对象都要实现Serializable接口*/ private void streamClonrTest(){ Person person = new Person("我", 13,new Email("我")); Person person1 = CloneUtils.clone(person); Person person2 = CloneUtils.clone(person); System.out.println("person : 【"+person+"】"); System.out.println("person1 : 【"+person1+"】"); System.out.println("person2 : 【"+person2+"】"); person.getEmail().setContent("你"); System.out.println("之后的person : 【"+person+"】"); System.out.println("之后的person1 : 【"+person1+"】"); System.out.println("之后的person2 : 【"+person2+"】"); }
private static void change(String x) { x = "ab"; }
private static void change(int x) { x = 2; }
private static void change(Person x) { x = new Person("你", 20, new Email("你")); }
private long qianCopyCost(){ long start = System.currentTimeMillis(); Person person = new Person("我", 13,new Email("我")); List<Person> list = new ArrayList<>(); for(int i = 0;i<=10000;i++){ list.add(new Person("你", 20, new Email("你"))); } return System.currentTimeMillis()-start; }
private long CloneCopyCost(){ long start = System.currentTimeMillis(); Person person = new Person("我", 13,new Email("我")); List<Person> list = new ArrayList<>(); for(int i = 0;i<=10000;i++){ list.add(person.clone()); } return System.currentTimeMillis()-start; }
private long StreamCopyCost(){ long start = System.currentTimeMillis(); Person person = new Person("我", 13,new Email("我")); List<Person> list = new ArrayList<>(); for(int i = 0;i<=10000;i++){ list.add(CloneUtils.clone(person)); } return System.currentTimeMillis()-start; }
}
class Person implements Serializable, Cloneable {
private static final long serialVersionUID = -8584225043397465132L; private String name; private int age;
public void setEmail(Email email) { this.email = email; }
private Email email;
public Email getEmail() { return email; }
public void setName(String name) { this.name = name; }
public void setAge(int age) { this.age = age; }
public Person(String name, int age, Email email) { this.name = name; this.age = age; this.email = email; }
@Override public String toString() { return "name : " + name + " | age : " + age +" | content : "+email.getContent(); }
@Override protected Person clone() { Person person = null; try { person = (Person) super.clone(); /*如果加上下一行 [使用clone深拷贝] 就不会改一处其他都改变了*/ person.setEmail( new Email(person.getEmail().getContent())); } catch (CloneNotSupportedException e) { e.printStackTrace(); }
return person; } }
class Email implements Serializable {
private static final long serialVersionUID = 1426052929769365539L; private String content;
public void setContent(String content) { this .content = content; }
public String getContent() { return content; }
public Email(String content) { this .content = content; } } |
测试了一下时间:
输出:
-------浅拷贝---------
cd
cd
1
name : 我 | age : 13 | content : 我
--------使用clone深拷贝--------
person : 【name : 我 | age : 13 | content : 我】
person1 : 【name : 我 | age : 13 | content : 我】
person2 : 【name : 我 | age : 13 | content : 我】
之后的person : 【name : 我 | age : 13 | content : 你】
之后的person1 : 【name : 我 | age : 13 | content : 我】
之后的person2 : 【name : 我 | age : 13 | content : 我】
--------使用序列化实现对象的拷贝--------
person : 【name : 我 | age : 13 | content : 我】
person1 : 【name : 我 | age : 13 | content : 我】
person2 : 【name : 我 | age : 13 | content : 我】
之后的person : 【name : 我 | age : 13 | content : 你】
之后的person1 : 【name : 我 | age : 13 | content : 我】
之后的person2 : 【name : 我 | age : 13 | content : 我】
--------耗时对比--------
耗时1 : 2
耗时2 : 1
耗时3 : 338
以上所述是小编给大家介绍的java中的深拷贝和浅拷贝(clone()方法的重写、使用序列化实现真正的深拷贝)详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
原文链接:https://blog.csdn.net/changshuchao/article/details/88406171
查看更多关于详解java中的深拷贝和浅拷贝(clone()方法的重写、使用序列化实现真正的深拷贝)的详细内容...