本篇文章給大家分享的是有關(guān)Java中怎么通過創(chuàng)建對象來提升程序性能,小編覺得挺實用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
目前成都創(chuàng)新互聯(lián)已為上千多家的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)站空間、網(wǎng)站托管、企業(yè)網(wǎng)站設(shè)計、格爾木網(wǎng)站維護等服務(wù),公司將堅持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。
在 Java 中有多種方式可以創(chuàng)建對象,總結(jié)起來主要有下面的 4 種方式:
正常創(chuàng)建:通過 new 操作符
反射創(chuàng)建:調(diào)用 Class 或 java.lang.reflect.Constructor 的 newInstance()方法
克隆創(chuàng)建:調(diào)用現(xiàn)有對象的 clone()方法
發(fā)序列化:調(diào)用 java.io.ObjectInputStream 的 getObject()方法反序列化
Java 對象的創(chuàng)建方式是其語法明確規(guī)定,用戶不可能從外部改變的。本文仍然要使用上面的方式來創(chuàng)建對象,所以本文只能說是構(gòu)建對象,而非創(chuàng)建對象也。
假設(shè)有這樣一個場景,現(xiàn)在要構(gòu)建一個大型的對象,這個對象包含許多個參數(shù)的對象,有些參數(shù)有些是必填的,有些則是選填的。那么如何構(gòu)建優(yōu)雅、安全地構(gòu)建這個對象呢?
01 單一構(gòu)造函數(shù)
通常,我們第一反應(yīng)能想到的就是單一構(gòu)造函數(shù)方式。直接 new 的方式構(gòu)建,通過構(gòu)造函數(shù)來傳遞參數(shù),見下面的代碼:
/*** * 單一構(gòu)造函數(shù) */ public class Person { // 姓名(必填) private String name; // 年齡(必填) private int age; // 身高(選填) private int height; // 畢業(yè)學(xué)校(選填) private String school; // 愛好(選填) private String hobby; public Person(String name, int age, int height, String school, String hobby) { this.name = name; this.age = age; this.height = height; this.school = school; this.hobby = hobby; } }
上面的構(gòu)建方式有下面的缺點:
有些參數(shù)是可以選填的(如 height, school),在構(gòu)建 Person 的時候必須要傳入可能并不需要的參數(shù)。
現(xiàn)在上面才 5 個參數(shù),構(gòu)造函數(shù)就已經(jīng)非常長了。如果是 20 個參數(shù),構(gòu)造函數(shù)都可以直接上天了!
構(gòu)建的這樣的對象非常容易出錯。
客戶端必須要對照 Javadoc 或者參數(shù)名來講實參傳入對應(yīng)的位置。如果參數(shù)都是 String 類型的,一旦傳錯參數(shù),編譯是不會報錯的,但是運行結(jié)果卻是錯誤的。
02 多構(gòu)造函數(shù)
對于第 1 個問題,我們可以通過構(gòu)造函數(shù)重載來解決。見下面的代碼:
/*** * 多構(gòu)造函數(shù) */ public class Person { // 姓名(必填) private String name; // 年齡(必填) private int age; // 身高(選填) private int height; // 畢業(yè)學(xué)校(選填) private String school; // 愛好(選填) private String hobby; public Person(String name, int age) { this.name = name; this.age = age; } public Person(String name, int age, int height) { this.name = name; this.age = age; this.height = height; } public Person(String name, int age, int height, String school) { this.name = name; this.age = age; this.height = height; this.school = school; } public Person(String name, int age, String hobby, String school) { this.name = name; this.age = age; this.hobby = hobby; this.school = school; } }
上面的方式確實能在一定程度上降低構(gòu)造函數(shù)的長度,但是卻有下面的缺陷:
導(dǎo)致類過長。這種方式會使得 Person 類的構(gòu)造函數(shù)成階乘級增長。按理來說,應(yīng)該要寫的構(gòu)造函數(shù)數(shù)是可選成員變量的組合數(shù)(實際并沒有這么多,原因見第 2 點)。如果讓我調(diào)用這樣的類,絕對會在心里默念 xx!!
有些參數(shù)組合無法重構(gòu)。因為 Java 中重載是有限制的,相同方法簽名的方法不能構(gòu)成重載,編譯時無法通過。譬如包含(name, age, school)和(name, age, hobby)的構(gòu)造函數(shù)是不能重載的,因為 shcool 和 hobby 同為 String 類型。Java 只認變量的類型,管你變量是什么含義呢。
03 JavaBean方式
上面的方法不行,莫急!還有法寶——JavaBean。一個對象的構(gòu)建通過多個方法來完成。直接見下面的代碼:
public class Person { // 姓名(必填) private String name; // 年齡(必填) private int age; // 身高(選填) private int height; // 畢業(yè)學(xué)校(選填) private String school; // 愛好(選填) private String hobby; public Person(String name, int age) { this.name = name; this.age = age; } public void setHeight(int height) { this.height = height; } public void setSchool(String school) { this.school = school; } public void setHobby(String hobby) { this.hobby = hobby; } } 客戶端使用這個對象的代碼如下: public class Client { public static void main(String[] args) { Person person = new Person("james", 12); person.setHeight(170); person.setHobby("reading"); person.setSchool("xxx university"); } }
這樣看起來完美的解決了 Person 對象構(gòu)建的問題,使用起來非常優(yōu)雅便捷。確實,在單一線程的環(huán)境中這確實是一個非常好的構(gòu)建對象的方法,但是如果是在多線程環(huán)境中仍有其致命缺陷。在多線程環(huán)境中,這個對象不能安全地被構(gòu)建,因為它不是不可變對象。一旦Person 對象被構(gòu)建,我們隨時可通過 setXXX()方法改變對象的內(nèi)部狀態(tài)。假設(shè)有一個線程正在執(zhí)行與 Person 對象相關(guān)的業(yè)務(wù)方法,另外一個線程改變了其內(nèi)部狀態(tài),這樣得到莫名其妙的結(jié)果。由于線程運行的無規(guī)律性,使得這問題有可能不能重現(xiàn),這個時候真的就只能哭了。
04 Builder方式
為了完美地解決這個問題,下面引出本文中的主角(等等等等!)。我們使用構(gòu)建器(Builder)來優(yōu)雅、安全地構(gòu)建 Person 對象。廢話不說,直接代碼:
/** * 待構(gòu)建的對象。該對象的特點: * <ol> * <li>需要用戶手動的傳入多個參數(shù),并且有多個參數(shù)是可選的、順序隨意</li> * <li>該對象是不可變的(所謂不可變,就是指對象一旦創(chuàng)建完成,其內(nèi)部狀態(tài)不可變, 更通俗的說是其成員變量不可改變)。* 不可變對象本質(zhì)上是線程安全的。</li> * <li>對象所屬的類不是為了繼承而設(shè)計的。</li> * </ol> * 滿足上面特點的對象的構(gòu)建可是使用下面的 Build 方式構(gòu)建。這樣構(gòu)建對象有下面的好 處: * <ol> * <li>不需要寫多個構(gòu)造函數(shù),使得對象的創(chuàng)建更加便捷</li> * <li>創(chuàng)建對象的過程是線程安全的</li> * </ol> * @author xiaoyu * @date 2020-10-25 */ public class Person { // 姓名(必填),final 修飾 name 一旦被初始化就不能再改變,保證了對象的不可變 性。 private final String name; // 年齡(必填) private final int age; // 身高(選填) private final int height; // 畢業(yè)學(xué)校(選填) private final String school; // 愛好(選填) private final String hobby; /** * 這個私有構(gòu)造函數(shù)的作用: * <ol> * <li>成員變量的初始化。final 類型的變量必須進行初始化,否則無法編譯成功</li> * <li>私有構(gòu)造函數(shù)能夠保證該對象無法從外部創(chuàng)建,并且 Person 類無法被繼承</li> * </ol> */ private Person(String name, int age, int height, String school, String hobby) { this.name = name; this.age = age; this.height = height; this.school = school; this.hobby = hobby; } /** * 要執(zhí)行的動作 */ public void doSomething() { // TODO do what you want!! } /** * 構(gòu)建器。為什么 Builder 是內(nèi)部靜態(tài)類? * <ol> * <li>必須是 Person 的內(nèi)部類。否則,由于 Person 的構(gòu)造函數(shù)私有,不能通過 new 的 方式創(chuàng)建 Person 對象</li> * <li>必須是靜態(tài)類。由于 Person 對象無法從外部創(chuàng)建,如果不是靜態(tài)類,則外部無 法引用 Builder 對象。</li> * </ol> * <b>注意</b>:Builder 內(nèi)部成員變量要與 Person 的成員變量保持一致。 * @author xiaoyu * */ public static class Builder { // 姓名(必填)。注意:這里不能是 final 的 private String name; // 年齡(必填) private int age; // 身高(選填) private int height; // 畢業(yè)學(xué)校(選填) private String school; // 愛好(選填) private String hobby; public Builder(String name, int age) { this.name = name; this.age = age; } public Builder setHeight(int height) { this.height = height; return this; } public Builder setSchool(String school) { this.school = school; return this; } public Builder setHobby(String hobby) { this.hobby = hobby; return this; } /** * 構(gòu)建對象 * @return 返回待構(gòu)建的對象本身 */ public Person build() { return new Person(name, age, height, school, hobby); } } }
客戶端構(gòu)建對象的方式見下面的代碼:
/** * 使用 Person 對象的客戶端 * @author xiaoyu * @date 2020-10-25 */ public class Client { public static void main(String[] args) { /* * 通過鏈式調(diào)用的方式創(chuàng)建 Person 對象,非常優(yōu)雅! */ Person person = new Person.Builder("james", 12) .setHeight(170) .setHobby("reading") .build(); person.doSomething(); } }
如果不想看代碼,可看下面對于上面代碼的總結(jié):
通過 private Person(..)使得 Person 類不可被繼承
通過將 Person 類的成員變量設(shè)置為 final 類型,使得其不可變
通過 Person 內(nèi)部的 static Builder 類來構(gòu)建 Person 對象
通過將 Builder 類內(nèi)部的 setXXX()方法返回 Builder 類型本身,實現(xiàn)鏈式調(diào)用構(gòu)建 Person 對 象
總結(jié)
至此,我們就相對完美地解決這一類型的對象創(chuàng)建問題!下面來總結(jié)一下本文的重點。待創(chuàng)建的對象特點:
需要用戶手動的傳入多個參數(shù),并且有多個參數(shù)是可選的、順序任意
對象不可變
對象所屬的類不是為了繼承而設(shè)計的。即類不能被繼承
依次使用的對象構(gòu)建方法:
單一構(gòu)造函數(shù)
多構(gòu)造函數(shù)
JavaBean 方式
Builder 方式
最終,通過比較得出 Builder 方法最為合適的解決。
以上就是Java中怎么通過創(chuàng)建對象來提升程序性能,小編相信有部分知識點可能是我們?nèi)粘9ぷ鲿姷交蛴玫降?。希望你能通過這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
網(wǎng)站標題:Java中怎么通過創(chuàng)建對象來提升程序性能
當(dāng)前URL:http://jinyejixie.com/article18/jpdjgp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站改版、App開發(fā)、品牌網(wǎng)站設(shè)計、品牌網(wǎng)站制作、品牌網(wǎng)站建設(shè)、虛擬主機
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)