Java創(chuàng)建對(duì)象的常見(jiàn)方式技術(shù)指南
1、簡(jiǎn)述
在 Java 開(kāi)發(fā)中,“對(duì)象”是一切面向?qū)ο缶幊痰幕A(chǔ)。Java 提供了多種方式來(lái)創(chuàng)建對(duì)象,不同方式背后有不同的應(yīng)用場(chǎng)景與運(yùn)行機(jī)制。理解這些方法,對(duì)于提升系統(tǒng)性能、掌握底層機(jī)制都有重要價(jià)值。
2、創(chuàng)建對(duì)象
2.1 使用 new 關(guān)鍵字(最常見(jiàn))
示例代碼:
public class User { String name; } ???????User user = new User();
說(shuō)明:
- 最常見(jiàn)、最直觀的方式。
- 會(huì)調(diào)用構(gòu)造方法,分配內(nèi)存并初始化對(duì)象。
- 編譯期類(lèi)型安全,適用于絕大多數(shù)場(chǎng)景。
2.2 使用反射 Class.newInstance()(不推薦)
示例代碼:
Class<?> clazz = Class.forName("com.example.User"); User user = (User) clazz.newInstance();
注意事項(xiàng):
- 要求類(lèi)必須有無(wú)參構(gòu)造方法。
- 在 Java 9 后被標(biāo)記為過(guò)時(shí)(deprecated),建議使用 getDeclaredConstructor().newInstance() 替代。
- 會(huì)拋出 InstantiationException、IllegalAccessException。
2.3 使用反射 Constructor.newInstance()(推薦反射方式)
示例代碼:
Constructor<User> constructor = User.class.getDeclaredConstructor(); constructor.setAccessible(true); User user = constructor.newInstance();
特點(diǎn):
- 支持調(diào)用私有構(gòu)造方法。
- 更靈活、安全(可以指定構(gòu)造函數(shù)參數(shù))。
- 常用于依賴注入、框架內(nèi)部如 Spring、MyBatis。
2.4 使用 clone() 方法(淺拷貝)
示例代碼:
public class User implements Cloneable { String name; @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } // 使用 User user1 = new User(); user1.name = "Tom"; User user2 = (User) user1.clone();
特點(diǎn):
- 克隆一個(gè)已存在的對(duì)象,屬于對(duì)象復(fù)制而非創(chuàng)建全新結(jié)構(gòu)。
- 默認(rèn)是淺拷貝,若包含引用類(lèi)型字段需手動(dòng)實(shí)現(xiàn)深拷貝。
- 需要實(shí)現(xiàn) Cloneable 接口,否則拋出 CloneNotSupportedException。
2.5 使用反序列化(從字節(jié)流創(chuàng)建)
示例代碼:
// 序列化 ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("user.ser")); out.writeObject(user); // 反序列化 ObjectInputStream in = new ObjectInputStream(new FileInputStream("user.ser")); User user2 = (User) in.readObject();
特點(diǎn):
- 常用于網(wǎng)絡(luò)傳輸、緩存存儲(chǔ)等場(chǎng)景。
- 類(lèi)必須實(shí)現(xiàn) Serializable 接口。
- 會(huì)跳過(guò)構(gòu)造方法的調(diào)用(繞過(guò) init 階段)。
2.6 使用對(duì)象工廠(工廠模式)
示例代碼:
public class UserFactory { public static User createUser(String name) { User user = new User(); user.name = name; return user; } }
特點(diǎn):
- 封裝對(duì)象創(chuàng)建邏輯,便于集中管理。
- 工廠模式是實(shí)際開(kāi)發(fā)中常用設(shè)計(jì)模式之一。
- Spring 中的 BeanFactory / ApplicationContext 就是這種思想。
2.7 使用第三方庫(kù):如 CGLIB、Objenesis
CGLIB 動(dòng)態(tài)代理創(chuàng)建對(duì)象(無(wú)構(gòu)造函數(shù)調(diào)用)
Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(User.class); enhancer.setCallback(new NoOp() {}); User proxyUser = (User) enhancer.create();
Objenesis
Objenesis objenesis = new ObjenesisStd(); User user = objenesis.newInstance(User.class);
特點(diǎn):
- 用于創(chuàng)建不調(diào)用構(gòu)造函數(shù)的對(duì)象(繞過(guò) new、反射等限制)。
- Spring、Mockito、Hibernate 等底層使用場(chǎng)景廣泛。
- 不適合日常業(yè)務(wù)開(kāi)發(fā),更多用于框架底層實(shí)現(xiàn)。
2.8 總結(jié)對(duì)比
方式 | 是否調(diào)用構(gòu)造函數(shù) | 是否常用 | 應(yīng)用場(chǎng)景 |
---|---|---|---|
new | ? 是 | ? 常用 | 普通對(duì)象創(chuàng)建 |
Class.newInstance() | ? 是 | ? 已過(guò)時(shí) | 框架反射,舊代碼中偶見(jiàn) |
Constructor.newInstance() | ? 是 | ? 推薦 | Spring、框架依賴注入 |
clone() | ? 否(復(fù)制) | ?? 慎用 | 對(duì)象拷貝、實(shí)現(xiàn)原型模式 |
反序列化 | ? 否 | ?? 慎用 | 網(wǎng)絡(luò)傳輸、緩存恢復(fù) |
工廠方法 | ? 是 | ? 常用 | 面向接口編程、統(tǒng)一對(duì)象創(chuàng)建入口 |
Objenesis / CGLIB | ? 否 | ? 框架級(jí) | Spring、Mock 框架底層、ORM 動(dòng)態(tài)代理 |
實(shí)踐建議
日常開(kāi)發(fā):首選 new 或工廠方法,代碼清晰,易維護(hù)。
框架開(kāi)發(fā):選擇反射 Constructor.newInstance() 或 Objenesis。
對(duì)象復(fù)制:優(yōu)先考慮手動(dòng)復(fù)制或使用庫(kù)如 Apache Commons Lang 的 SerializationUtils,避免使用 clone()。
性能敏感:避免使用反序列化方式,風(fēng)險(xiǎn)高、開(kāi)銷(xiāo)大。
3、結(jié)語(yǔ)
Java 提供了多種方式創(chuàng)建對(duì)象,不同方式各有適用場(chǎng)景。掌握它們不僅有助于寫(xiě)出更靈活的代碼,也有助于深入理解如 Spring、MyBatis、Dubbo 等優(yōu)秀框架的實(shí)現(xiàn)原理。推薦大家多動(dòng)手實(shí)踐,如自己實(shí)現(xiàn)一個(gè)對(duì)象工廠,或基于反射構(gòu)建簡(jiǎn)單容器,進(jìn)一步鞏固理解。
如果你想,我可以繼續(xù)提供以下內(nèi)容:
- 示例源碼項(xiàng)目結(jié)構(gòu)(含反射、clone、Objenesis等示例)
- 對(duì)比幾種方式的創(chuàng)建性能(Benchmark)
- 與 Spring Bean 創(chuàng)建過(guò)程的對(duì)應(yīng)關(guān)系
到此這篇關(guān)于Java創(chuàng)建對(duì)象的常見(jiàn)方式技術(shù)指南的文章就介紹到這了,更多相關(guān)Java創(chuàng)建對(duì)象內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mybatis-generator-gui根據(jù)需求改動(dòng)示例
這篇文章主要為大家介紹了mybatis-generator-gui根據(jù)需求改動(dòng)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09Caused by: java.io.IOException: DerInputStrea
這篇文章主要介紹了Caused by: java.io.IOException: DerInputStream.getLength(): lengthTag=111, too big,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-10-10簡(jiǎn)單了解Spring Boot及idea整合jsp過(guò)程解析
這篇文章主要介紹了簡(jiǎn)單了解Spring Boot及idea整合jsp過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11Docker搭建前端Java的開(kāi)發(fā)環(huán)境詳解
相信每個(gè)人入職第一天就是搭建本地開(kāi)發(fā)環(huán)境,因?yàn)槲宜居玫氖莏ava,看見(jiàn)了多年不見(jiàn)的eclipse的圖標(biāo)出現(xiàn)我的電腦上,我是難過(guò)的。后來(lái)知道并不是我一個(gè)人有此感受。這篇文章是為了解決前后端開(kāi)發(fā)沒(méi)有徹底分離的坑,詳細(xì)的給大家介紹了利用Docker搭建前端Java的開(kāi)發(fā)環(huán)境。2016-10-10mybatis-generator自動(dòng)生成dao、mapping、bean配置操作
這篇文章主要介紹了mybatis-generator自動(dòng)生成dao、mapping、bean配置操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08IDEA全量替換一次性解決舊項(xiàng)目并將所有文件換行符改為L(zhǎng)F問(wèn)題
這篇文章主要介紹了IDEA全量替換一次性解決舊項(xiàng)目并將所有文件換行符改為L(zhǎng)F問(wèn)題,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友參考下2019-05-05Java volatile關(guān)鍵字原理剖析與實(shí)例講解
volatile是Java提供的一種輕量級(jí)的同步機(jī)制,Java?語(yǔ)言包含兩種內(nèi)在的同步機(jī)制:同步塊(或方法)和?volatile?變量,本文將詳細(xì)為大家總結(jié)Java volatile關(guān)鍵字,通過(guò)詳細(xì)的代碼示例給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-07-07