Java方法中的参数太多,第1部分:自定义类型
我認(rèn)為構(gòu)造函數(shù)和方法中冗長的參數(shù)列表是Java開發(fā)中的另一個“ 危險信號 ”,就邏輯和功能而言,它們不一定是“錯誤的”,但通常暗示當(dāng)前或?qū)沓霈F(xiàn)錯誤的可能性很高。 在一小部分帖子中,我介紹了一些可用于減少方法或構(gòu)造函數(shù)的參數(shù)數(shù)量,或至少使冗長的參數(shù)列表更易讀且更不易出錯的方法。 每種方法都有其自己的優(yōu)點和缺點。 這篇文章開始該系列文章,重點是通過使用自定義類型提高長方法/構(gòu)造函數(shù)參數(shù)列表的可讀性和安全性。
冗長的方法和構(gòu)造方法參數(shù)列表有幾個缺點。 大量參數(shù)可能很乏味,并且難以調(diào)用代碼使用。 較長的參數(shù)列表也可能導(dǎo)致調(diào)用中參數(shù)的無意切換。 在某些情況下,可能很難找到這些錯誤。 幸運的是,大多數(shù)方法不必處理冗長的參數(shù)列表的另一個缺點: JVM通過編譯時錯誤 將參數(shù)的數(shù)量限制為一個方法 。
自定義類型的使用是一種不減少方法或構(gòu)造函數(shù)的參數(shù)數(shù)量,但確實使這些較長的參數(shù)列表更易讀且不太可能以錯誤的順序提供的方法。 這些自定義類型可以實現(xiàn)為數(shù)據(jù)傳輸對象 (DTO), JavaBeans , 值對象 , 引用對象或任何其他自定義類型(在Java中,通常是類或枚舉 )。
這是一個人為設(shè)計的方法示例,該方法接受多個參數(shù),其中許多參數(shù)為String類型,許多參數(shù)為boolean類型。
/*** Instantiate a Person object.* * @param lastName* @param firstName* @param middleName* @param salutation* @param suffix* @param streetAddress* @param city* @param state* @param isFemale* @param isEmployed* @param isHomeOwner* @return */public Person createPerson(final String lastName,final String firstName,final String middleName,final String salutation,final String suffix,final String streetAddress,final String city,final String state,final boolean isFemale,final boolean isEmployed,final boolean isHomeOwner){// implementation goes here}容易意外地切換它們并以錯誤的順序傳遞它們。 盡管我通常希望減少參數(shù),但是可以通過更改參數(shù)列表中的類型來進(jìn)行一些改進(jìn)。 接下來的代碼清單顯示了這些自定義類型的一些示例,這些示例可用于名稱,地址,城市和布爾參數(shù)。
可以將三個name參數(shù)分別更改為Name的自定義類型,而不是String 。 接下來定義該Name類型。
名稱.java
package dustin.examples;/*** Name representation.* * @author Dustin*/ public final class Name {private final String name;public Name(final String newName){this.name = newName;}public String getName(){return this.name;}@Overridepublic String toString(){return this.name;} }稱呼和后綴String類型也可以替換為自定義類型,如以下兩個代碼清單所示。
Salutation.java
package dustin.examples;/*** Salutations for individuals' names.* * @author Dustin*/ public enum Salutation {DR,MADAM,MISS,MR,MRS,MS,SIR }后綴.java
package dustin.examples;/*** Suffix representation.* * @author Dustin*/ public enum Suffix {III,IV,JR,SR }其他參數(shù)也可以用自定義類型替換。 接下來的代碼清單顯示了可以替換boolean以提高可讀性的自定義枚舉。
Gender.java
package dustin.examples;/*** Gender representation.* * @author Dustin*/ public enum Gender {FEMALE,MALE }EmploymentStatus.java
package dustin.examples;/*** Representation of employment status.* * @author Dustin*/ public enum EmploymentStatus {EMPLOYED,NOT_EMPLOYED }HomeOwnerStatus.java
package dustin.examples;/*** Representation of homeowner status.* * @author Dustin*/ public enum HomeownerStatus {HOME_OWNER,RENTER }也可以使用定義的自定義類型來傳遞此人的地址信息,如以下代碼清單所示。
StreetAddress.java
package dustin.examples;/*** Street Address representation.* * @author Dustin*/ public final class StreetAddress {private final String address;public StreetAddress(final String newStreetAddress){this.address = newStreetAddress;}public String getAddress(){return this.address;}@Overridepublic String toString(){return this.address;} }City.java
package dustin.examples;/*** City representation.* * @author Dustin*/ public final class City {private final String cityName;public City(final String newCityName){this.cityName = newCityName;}public String getCityName(){return this.cityName;}@Overridepublic String toString(){return this.cityName;} }State.java
package dustin.examples;/*** Simple representation of a state in the United States.* * @author Dustin*/ public enum State {AK,AL,AR,AZ,CA,CO,CT,DE,FL,GA,HI,IA,ID,IL,IN,KS,KY,LA,MA,MD,ME,MI,MN,MO,MS,MT,NC,ND,NE,NH,NJ,NM,NV,NY,OH,OK,OR,PA,RI,SC,SD,TN,TX,UT,VA,VT,WA,WI,WV,WY }通過實現(xiàn)這些自定義類型,我們原始方法的簽名變得更具可讀性,并且不太可能意外地以錯誤的順序提供參數(shù)。 這顯示在下一個代碼清單中。
public Person createPerson(final Name lastName,final Name firstName,final Name middleName,final Salutation salutation,final Suffix suffix,final StreetAddress address,final City city,final State state,final Gender gender,final EmploymentStatus employment,final HomeownerStatus homeowner){// implementation goes here}在上面的代碼清單中,編譯器現(xiàn)在將通過不允許之前的大多數(shù)String或boolean參數(shù)意外混合來幫助開發(fā)人員。 這三個名稱仍然是一個潛在的問題,因為調(diào)用方可能會無序提供它們,但是如果我擔(dān)心的話,我可以為FirstName , LastName和MiddleName編寫特定的類型(類)。 相反,我更喜歡使用一個代表全名的新類,并將這三個名稱全部用作其屬性,但是該方法將成為以后處理Java方法的過多參數(shù)的主題。
優(yōu)勢與優(yōu)勢
在給定方法上處理多個參數(shù)時編寫和使用自定義類型的優(yōu)點包括代碼維護(hù)者和使用API??的開發(fā)人員的可讀性。 具有多個相同類型的參數(shù),不僅使開發(fā)人員可以輕松混合其順序,還降低了IDE在使用代碼完成功能時將適當(dāng)建議與參數(shù)匹配的能力。 正確的命名可以對IDE有所幫助,但是對IDE而言,沒有什么比使用這些自定義類型可以完成的靜態(tài)編譯時檢查有用的了。 總的來說,我更愿意從運行時轉(zhuǎn)移盡可能多的自動檢查到編譯時,并且讓這些靜態(tài)定義的自定義類型(而不是通用類型)來完成此任務(wù)。
此外,這些自定義類型的存在使將來更容易添加更多詳細(xì)信息。 例如,將來我可以在不更改接口的情況下,將完整的狀態(tài)名稱或有關(guān)狀態(tài)的其他詳細(xì)信息添加到該枚舉中。 我不可能用一個簡單的String來表示狀態(tài)。
成本與劣勢
自定義類型方法最常被引用的缺點之一是額外的實例化和內(nèi)存使用的開銷。 例如, Name類需要實例化Name類本身及其封裝的String 。 但是,我認(rèn)為,這種爭論通常是從過早優(yōu)化的角度出發(fā),而不是合理的衡量性能問題。 在某些情況下,額外的實例化過于昂貴,以至于無法證明增強(qiáng)的可讀性和編譯時檢查,但是許多(也許大多數(shù) )情況可以提供額外的實例化,而其可觀察到的影響卻可以忽略不計。 我很難相信使用自定義枚舉而不是String或boolean會在大多數(shù)情況下引入性能問題。
使用自定義類型而不是內(nèi)置類型的另一個缺點是編寫和測試這些自定義類型需要額外的精力。 但是,如本文中的示例所示,通常存在非常簡單的類或枚舉,并且不難編寫或測試。 有了良好的IDE和良好的腳本語言(例如Groovy),它們特別容易自動編寫和測試。
結(jié)論
我喜歡使用自定義類型來提高可讀性,并將更多的參數(shù)類型檢查負(fù)擔(dān)轉(zhuǎn)移到編譯器上。 我沒有更多地使用這種方法來提高具有非常長的參數(shù)列表的方法和構(gòu)造函數(shù)的可讀性的最大原因是,它本身并沒有減少參數(shù)的數(shù)量。 它使長列表更易于閱讀和使用,但調(diào)用方仍然必須編寫笨拙的客戶端代碼才能調(diào)用該方法或構(gòu)造函數(shù)。 因此,在改進(jìn)接受一長串參數(shù)的方法時,我經(jīng)常使用除自定義類型以外的技術(shù)。 這些其他技術(shù)將在以后的文章中探討。
翻譯自: https://www.javacodegeeks.com/2013/10/too-many-parameters-in-java-methods-part-1-custom-types.html
總結(jié)
以上是生活随笔為你收集整理的Java方法中的参数太多,第1部分:自定义类型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 常见Java错误的十大列表(前100名!
- 下一篇: 大逆转裁判2安卓汉化(大逆转裁判2安卓)