Java中new與clone操作對(duì)象的比較方法舉例
1、new操作符創(chuàng)建對(duì)象的過(guò)程
new操作符在Java中用于創(chuàng)建對(duì)象,并執(zhí)行以下步驟:
- 分配內(nèi)存空間: 根據(jù)類型確定所需內(nèi)存大小。
- 調(diào)用構(gòu)造函數(shù): 初始化對(duì)象的各個(gè)域。
- 返回對(duì)象引用: 可以將引用發(fā)布到外部,使得對(duì)象可以被使用。
示例代碼:
MyClass obj = new MyClass();
new MyClass()創(chuàng)建了一個(gè)MyClass類型的對(duì)象并分配了內(nèi)存空間。
2、clone方法創(chuàng)建對(duì)象的過(guò)程
- 分配內(nèi)存與初始化:
- clone方法和new操作符都會(huì)分配內(nèi)存。但是,clone方法分配的內(nèi)存大小與原對(duì)象相同。
- 不同于new操作符,clone方法不會(huì)調(diào)用構(gòu)造函數(shù)來(lái)初始化對(duì)象的域。而是使用原對(duì)象的值填充新對(duì)象的域。這稱為 淺拷貝(shallow copy)。
- 淺拷貝與深拷貝的區(qū)別:
- 如果對(duì)象的域中引用了其他對(duì)象(例如數(shù)組或其他類的實(shí)例),clone方法只會(huì)復(fù)制引用,而不會(huì)復(fù)制引用指向的對(duì)象本身。
- 這就是淺拷貝和深拷貝的區(qū)別:淺拷貝復(fù)制引用,深拷貝則會(huì)遞歸復(fù)制引用的對(duì)象。
- 返回新對(duì)象:
- 當(dāng)clone方法執(zhí)行完畢后,將會(huì)創(chuàng)建一個(gè)新的對(duì)象,其值與原對(duì)象相同(但內(nèi)存地址不同)。
- 我們可以將新對(duì)象的引用用于外部。
示例代碼:
MyClass original = new MyClass(); MyClass cloned = (MyClass) original.clone();
3、總結(jié)
1、new操作符:分配內(nèi)存并調(diào)用構(gòu)造函數(shù)初始化對(duì)象。
2、clone方法:分配內(nèi)存并使用原對(duì)象的值來(lái)填充新對(duì)象的域(淺拷貝)。
雖然new和clone都可以用來(lái)創(chuàng)建對(duì)象,但它們的使用場(chǎng)景和原理是不同的。在實(shí)際編程中,我們需要根據(jù)具體的需求來(lái)選擇使用哪種方式。
附:clone()和new那個(gè)更快?
利用clone,在內(nèi)存中進(jìn)行數(shù)據(jù)塊的拷貝,復(fù)制已有的對(duì)象,也是生成對(duì)象的一種方式。前提是類實(shí)現(xiàn)Cloneable接口,Cloneable接口沒(méi)有任何方法,是一個(gè)空接口,也可以稱這樣的接口為標(biāo)志接口,只有實(shí)現(xiàn)了該接口,才會(huì)支持clone操作。有的人也許會(huì)問(wèn)了,java中的對(duì)象都有一個(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ù)制對(duì)象的時(shí)候,會(huì)檢查對(duì)象的類是否實(shí)現(xiàn)了Cloneable這個(gè)接口,如果沒(méi)有實(shí)現(xiàn),則會(huì)報(bào)CloneNotSupportedException異常。類似這樣的接口還有Serializable接口、RandomAccess接口等。
還有值得一提的是在執(zhí)行clone操作的時(shí)候,不會(huì)調(diào)用構(gòu)造函數(shù)。還有clone操作還會(huì)面臨深拷貝和淺拷貝的問(wèn)題。關(guān)于這方面的問(wèn)題,網(wǎng)上有很多的相關(guān)知識(shí)了,不再累述了。由于通過(guò)復(fù)制操作得到對(duì)象不需要調(diào)用構(gòu)造函數(shù),只是內(nèi)存中的數(shù)據(jù)塊的拷貝,那是不是拷貝對(duì)象的效率是不是一定會(huì)比new的時(shí)候的快。
答案:不是。顯然jvm的開(kāi)發(fā)者也意識(shí)到通過(guò)new方式來(lái)生成對(duì)象占據(jù)了開(kāi)發(fā)者生成對(duì)象的絕大部分,所以對(duì)于利用new操作生成對(duì)象進(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)簡(jiǎn)單的事情,例如字符串截取試試。只是修改Bean,其他不變?cè)倏创蛴?/p>
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é)論:輕量級(jí)的對(duì)象可以使用new,其他對(duì)象可以使用clone。
到此這篇關(guān)于Java中new與clone操作對(duì)象的比較方法的文章就介紹到這了,更多相關(guān)Java new與clone操作對(duì)象比較內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot實(shí)現(xiàn)網(wǎng)頁(yè)消息推送的5種方法對(duì)比
網(wǎng)頁(yè)消息推送是現(xiàn)代 Web 應(yīng)用的核心功能之一,Spring Boot 提供了非常成熟的支持,本文為大家整理了 5 種主流實(shí)現(xiàn)方式,有需要的小伙伴可以了解下2026-02-02
Logger.getLogger()與LogFactory.getLog()的區(qū)別詳解
LogFactory來(lái)自common-logging包。如果用LogFactory.getLog,你可以用任何實(shí)現(xiàn)了通用日志接口的日志記錄器替換log4j,而程序不受影響2013-09-09
SpringBoot使用自定義注解實(shí)現(xiàn)數(shù)據(jù)脫敏過(guò)程詳細(xì)解析
這篇文章主要介紹了SpringBoot自定義注解之脫敏注解詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02
SpringBoot集成Swagger2生成接口文檔的方法示例
我們提供Restful接口的時(shí)候,API文檔是尤為的重要,它承載著對(duì)接口的定義,描述等,本文主要介紹了SpringBoot集成Swagger2生成接口文檔的方法示例,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-12-12
Springboot+Poi導(dǎo)入Excel表格實(shí)現(xiàn)過(guò)程詳解
這篇文章主要介紹了Springboot+Poi導(dǎo)入Excel表格實(shí)現(xiàn)過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09
這么優(yōu)雅的Java ORM沒(méi)見(jiàn)過(guò)吧!
這篇文章主要介紹了Java ORM的相關(guān)資料,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下2021-01-01
Java回調(diào)函數(shù)原理實(shí)例與代理模式的區(qū)別講解
今天小編就為大家分享一篇關(guān)于Java回調(diào)函數(shù)原理實(shí)例與代理模式的區(qū)別講解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-02-02

