您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關java中如何實現深拷貝和淺拷貝,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
1.序列化實現
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.主代碼
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中如何實現深拷貝和淺拷貝”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。