Java構(gòu)建對(duì)象常用3種方法解析
前言
當(dāng)我們面對(duì)具有大量可選成員變量的 Java 類時(shí),創(chuàng)建這些對(duì)象的最佳方法是什么?通常有三種方法: 伸縮構(gòu)造函數(shù),JavaBean模式和構(gòu)建器模式。
構(gòu)造函數(shù)
UserInfo userInfo1 = new UserInfo("felord.cn", 28);
UserInfo xxxxxx = new UserInfo("felord.cn", "xxxxxx", 28);
UserInfo xxxxxx1 = new UserInfo("felord.cn", "xxxxxx", 28, LocalDateTime.now());
構(gòu)造函數(shù)通常需要可伸縮性,也就是參數(shù)列表需要重載。有些時(shí)候我不得不傳入null進(jìn)行初始化。
// 不合理的構(gòu)造使用示范
UserInfo xxxxxx = new UserInfo(null, null, 28);
而且不能直觀看出這些參數(shù)所代表的的含義,這有可能引發(fā)致命的錯(cuò)誤,我們將同類型的username和address互換位置依然成功初始化了對(duì)象,不會(huì)顯式的引發(fā)構(gòu)建錯(cuò)誤,這是不合理的。
IDEA 參數(shù)列表提示功能
另外如果參數(shù)列表比較長(zhǎng),有七八個(gè)的話,代碼是非常冗長(zhǎng)的。
難道構(gòu)造函數(shù)一無(wú)是處嗎,當(dāng)然不是。胖哥在使用構(gòu)造參數(shù)時(shí)會(huì)確保構(gòu)造的參數(shù)列表不會(huì)太長(zhǎng),而且如果參數(shù)是可選的話,不會(huì)將其置于構(gòu)造函數(shù)中的。另外構(gòu)建不可變對(duì)象使用構(gòu)造函數(shù)也是極好的。
JavaBean
這種方式是最常用的創(chuàng)建對(duì)象的方法。只需要使用無(wú)參構(gòu)造函數(shù),然后為每個(gè)成員變量設(shè)置setter方法。
UserInfo userInfo = new UserInfo();
userInfo.setUsername("felord.cn");
userInfo.setAge(28);
這種方式之所以使用非常普遍是因?yàn)楹芏嘀蚣苄枰悴捎眠@種模式,比如JSON類庫(kù)Jackson、Spring Framework還有絕大部分的ORM框架。
大多數(shù)情況下這種方式是可以勝任的。它的缺點(diǎn)在于我們需要兩步來(lái)完成對(duì)象的創(chuàng)建工作,另外它缺乏創(chuàng)建不可變對(duì)象的能力。
構(gòu)建器
構(gòu)建器其實(shí)在我之前的文章多次用到,Spring Security對(duì)HttpSecurity的配置就用到了該模式。構(gòu)建器不僅獲得了伸縮構(gòu)造函數(shù)的安全性,而且可讀性更好。
我們需要在目標(biāo)對(duì)象(這里是UserInfo)內(nèi)部創(chuàng)建了一個(gè)靜態(tài)類,通常簡(jiǎn)單地稱為Builder。Builder聲明了一系列方法來(lái)設(shè)置對(duì)象屬性的值,然后將其返回Builder本身,完成所有調(diào)用后,我們調(diào)用Builder的無(wú)參build方法進(jìn)行目標(biāo)對(duì)象的初始化。
public class UserInfo {
private String username;
private String address;
private Integer age;
private LocalDateTime addTime;
// 私有化無(wú)參構(gòu)造
private UserInfo() {
}
public static class Builder {
private String username;
private Integer age;
private String address;
private LocalDateTime addTime;
public Builder username(String username) {
this.username = username;
return this;
}
public Builder address(String address) {
this.address = address;
return this;
}
public Builder age(Integer age) {
this.age = age;
return this;
}
public Builder addTime(LocalDateTime addTime) {
this.addTime = addTime;
return this;
}
public UserInfo build() {
UserInfo userInfo = new UserInfo();
userInfo.username = this.username;
userInfo.address = this.address;
userInfo.age = this.age;
userInfo.addTime = this.addTime;
return userInfo;
}
}
// 省略 getter
}
然后初始化對(duì)象就可以這么寫(xiě):
UserInfo userInfo = new UserInfo.Builder()
.username("felord.cn")
.address("xxxxxx")
.age(28)
.addTime(LocalDateTime.now())
.build();
這種寫(xiě)法首先很流暢,而且可讀性更高,同時(shí)靈活度也得到了保證,可選參數(shù)更易處理。但是這種模式增加了我們代碼的書(shū)寫(xiě)難度,需要進(jìn)行一些額外的定義。當(dāng)然你可以借助于Lombok框架的@Builder注解來(lái)直接使用構(gòu)建器模式,但是不是每個(gè)人都喜歡Lombok。
由于常用的第三方框架的原因,這種寫(xiě)法的使用場(chǎng)景并不是那么寬泛。通常在定義一些配置時(shí)使用它。可參考在這篇文章的做法。
總結(jié)
在Java日常開(kāi)發(fā)中構(gòu)造函數(shù)和JavaBean是我們最常用的創(chuàng)建對(duì)象的手段,構(gòu)建器的適用場(chǎng)景相對(duì)少了一些,但是在定義一些配置的時(shí)候還是非常有用的。好了今天就聊到這里,希望對(duì)你有所幫助。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
詳解 Java HashMap 實(shí)現(xiàn)原理
這篇文章主要介紹了詳解 Java HashMap 實(shí)現(xiàn)原理的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下2021-03-03
使用springmvc臨時(shí)不使用視圖解析器的自動(dòng)添加前后綴
這篇文章主要介紹了使用springmvc臨時(shí)不使用視圖解析器的自動(dòng)添加前后綴,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09
elasticsearch通過(guò)guice注入Node組裝啟動(dòng)過(guò)程
這篇文章主要為大家介紹了?elasticsearch通過(guò)guice注入Node組裝啟動(dòng)過(guò)程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04
SpringBoot詳細(xì)講解如何創(chuàng)建及刷新Spring容器bean
前面看spring源碼時(shí)可以發(fā)現(xiàn)refresh()方法十分重要。在這個(gè)方法中會(huì)加載beanDefinition,同時(shí)創(chuàng)建bean對(duì)象。那么在springboot中有沒(méi)有使用這個(gè)refresh()方法呢2022-06-06
Spring TransactionalEventListener事務(wù)未提交讀取不到數(shù)據(jù)的解決
這篇文章主要介紹了Spring TransactionalEventListener事務(wù)未提交讀取不到數(shù)據(jù)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09
一文搞懂接口參數(shù)簽名與驗(yàn)簽(附含java python php版)
這篇文章主要為大家介紹了java python php不同版的接口參數(shù)簽名與驗(yàn)簽示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06

