Java中new與clone操作對象的比較方法舉例
1、new操作符創(chuàng)建對象的過程
new操作符在Java中用于創(chuàng)建對象,并執(zhí)行以下步驟:
- 分配內(nèi)存空間: 根據(jù)類型確定所需內(nèi)存大小。
- 調(diào)用構(gòu)造函數(shù): 初始化對象的各個(gè)域。
- 返回對象引用: 可以將引用發(fā)布到外部,使得對象可以被使用。
示例代碼:
MyClass obj = new MyClass();
new MyClass()創(chuàng)建了一個(gè)MyClass類型的對象并分配了內(nèi)存空間。
2、clone方法創(chuàng)建對象的過程
- 分配內(nèi)存與初始化:
- clone方法和new操作符都會分配內(nèi)存。但是,clone方法分配的內(nèi)存大小與原對象相同。
- 不同于new操作符,clone方法不會調(diào)用構(gòu)造函數(shù)來初始化對象的域。而是使用原對象的值填充新對象的域。這稱為 淺拷貝(shallow copy)。
- 淺拷貝與深拷貝的區(qū)別:
- 如果對象的域中引用了其他對象(例如數(shù)組或其他類的實(shí)例),clone方法只會復(fù)制引用,而不會復(fù)制引用指向的對象本身。
- 這就是淺拷貝和深拷貝的區(qū)別:淺拷貝復(fù)制引用,深拷貝則會遞歸復(fù)制引用的對象。
- 返回新對象:
- 當(dāng)clone方法執(zhí)行完畢后,將會創(chuàng)建一個(gè)新的對象,其值與原對象相同(但內(nèi)存地址不同)。
- 我們可以將新對象的引用用于外部。
示例代碼:
MyClass original = new MyClass(); MyClass cloned = (MyClass) original.clone();
3、總結(jié)
1、new操作符:分配內(nèi)存并調(diào)用構(gòu)造函數(shù)初始化對象。
2、clone方法:分配內(nèi)存并使用原對象的值來填充新對象的域(淺拷貝)。
雖然new和clone都可以用來創(chuàng)建對象,但它們的使用場景和原理是不同的。在實(shí)際編程中,我們需要根據(jù)具體的需求來選擇使用哪種方式。
附:clone()和new那個(gè)更快?
利用clone,在內(nèi)存中進(jìn)行數(shù)據(jù)塊的拷貝,復(fù)制已有的對象,也是生成對象的一種方式。前提是類實(shí)現(xiàn)Cloneable接口,Cloneable接口沒有任何方法,是一個(gè)空接口,也可以稱這樣的接口為標(biāo)志接口,只有實(shí)現(xiàn)了該接口,才會支持clone操作。有的人也許會問了,java中的對象都有一個(gè)默認(rèn)的父類Object。
Object中有一個(gè)clone方法,為什么還必須要實(shí)現(xiàn)Cloneable接口呢,這就是cloneable接口這個(gè)標(biāo)志接口的意義,只有實(shí)現(xiàn)了這個(gè)接口才能實(shí)現(xiàn)復(fù)制操作,因?yàn)閖vm在復(fù)制對象的時(shí)候,會檢查對象的類是否實(shí)現(xiàn)了Cloneable這個(gè)接口,如果沒有實(shí)現(xiàn),則會報(bào)CloneNotSupportedException異常。類似這樣的接口還有Serializable接口、RandomAccess接口等。
還有值得一提的是在執(zhí)行clone操作的時(shí)候,不會調(diào)用構(gòu)造函數(shù)。還有clone操作還會面臨深拷貝和淺拷貝的問題。關(guān)于這方面的問題,網(wǎng)上有很多的相關(guān)知識了,不再累述了。由于通過復(fù)制操作得到對象不需要調(diào)用構(gòu)造函數(shù),只是內(nèi)存中的數(shù)據(jù)塊的拷貝,那是不是拷貝對象的效率是不是一定會比new的時(shí)候的快。
答案:不是。顯然jvm的開發(fā)者也意識到通過new方式來生成對象占據(jù)了開發(fā)者生成對象的絕大部分,所以對于利用new操作生成對象進(jìn)行了優(yōu)化。
例如:
package com.miivii.javalib; public class Bean implements Cloneable { private String name; public Bean(String name) { this.name = name; } @Override protected Bean clone() throws CloneNotSupportedException { return (Bean) super.clone(); } }
package com.miivii.javalib; public class TestClass { private static final int COUNT = 10000 * 1000; public static void main(String[] args) throws CloneNotSupportedException { long s1 = System.currentTimeMillis(); for (int i = 0; i < COUNT; i++) { Bean bean = new Bean("ylWang"); } long s2 = System.currentTimeMillis(); Bean bean = new Bean("ylWang"); for (int i = 0; i < COUNT; i++) { Bean b = bean.clone(); } long s3 = System.currentTimeMillis(); System.out.println("new = " + (s2 - s1)); System.out.println("clone = " + (s3 - s2)); } }
打印結(jié)果:
new完勝clone,真的是這樣嗎?
下面在構(gòu)造函數(shù)里做點(diǎn)簡單的事情,例如字符串截取試試。只是修改Bean,其他不變再看打印
package com.miivii.javalib; public class Bean implements Cloneable { private String name; private String firstSign;//獲取名字首字母 public Bean(String name) { this.name = name; if (name.length() != 0) { firstSign = name.substring(0, 1); firstSign += "abc"; } } @Override protected Bean clone() throws CloneNotSupportedException { return (Bean) super.clone(); } }
結(jié)論:輕量級的對象可以使用new,其他對象可以使用clone。
到此這篇關(guān)于Java中new與clone操作對象的比較方法的文章就介紹到這了,更多相關(guān)Java new與clone操作對象比較內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot中使用Guava實(shí)現(xiàn)單機(jī)令牌桶限流的示例
本文主要介紹了SpringBoot中使用Guava實(shí)現(xiàn)單機(jī)令牌桶限流的示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06@RequiredArgsConstructor如何實(shí)現(xiàn)構(gòu)造器注入
這篇文章主要介紹了@RequiredArgsConstructor如何實(shí)現(xiàn)構(gòu)造器注入問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-09-09Java 深入淺出分析Synchronized原理與Callable接口
Synchronized關(guān)鍵字解決的是多個(gè)線程之間訪問資源的同步性,synchronized關(guān)鍵字可以保證被它修飾的方法或者代碼塊在任意時(shí)刻只能有一個(gè)線程執(zhí)行,Runnable是執(zhí)行工作的獨(dú)立任務(wù),但是不返回任何值。如果我們希望任務(wù)完成之后有返回值,可以實(shí)現(xiàn)Callable接口2022-03-03json-lib將json格式的字符串,轉(zhuǎn)化為java對象的實(shí)例
下面小編就為大家?guī)硪黄猨son-lib將json格式的字符串,轉(zhuǎn)化為java對象的實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-03-03SpringBoot v2.2以上重復(fù)讀取Request Body內(nèi)容的解決方案
這篇文章主要介紹了SpringBoot v2.2以上重復(fù)讀取Request Body內(nèi)容的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10Java面試題沖刺第六天--網(wǎng)絡(luò)編程1
這篇文章主要為大家分享了最有價(jià)值的三道網(wǎng)絡(luò)編程面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,感興趣的小伙伴們可以參考一下2021-07-07MyBatis開發(fā)Dao層的兩種方式實(shí)現(xiàn)(原始Dao層開發(fā))
這篇文章主要介紹了MyBatis開發(fā)Dao層的兩種方式實(shí)現(xiàn)(原始Dao層開發(fā)),并對數(shù)據(jù)庫進(jìn)行增刪查改,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-12-12