Java方法中的参数太多,第4部分:重载
期望將過多的參數傳遞給Java方法的問題之一是,該方法的客戶端很難確定它們是否以適當的順序傳遞了適當的值。 在以前的文章中,我描述了如何使用自定義類型 , 參數對象和構建器來解決此問題。 解決此問題的另一種方法(也是本文的主題)是提供相同方法的重載版本 ,以使客戶可以使用最適合其需求的方法。 就像我之前關于過多方法參數的文章一樣,我將在本篇文章的結尾簡要討論這種方法的優缺點。
Java支持方法重載 ,即能夠通過其方法簽名區分同一方法的不同版本。 請注意,兩種方法之間唯一的區別是不同的返回類型通常不足以實現重載。
可能出于多種原因應用方法重載。 重載方法的一個目標可能是在不同類型上支持相同的功能(尤其是如果無法使用泛型來允許該方法支持不同類型,或者如果在泛型可用之前編寫了這些方法)。 考慮到此意圖的方法重載示例包括String.valueOf(boolean) , String.valueOf(char) , String.valueOf(double) , String.valueOf(long) , String.valueOf(Object)和其他一些版本String.valueOf重載在其他一些類型上。
選擇重載方法的另一個原因是,客戶端可以調用方法的適當版本以僅提供必要的參數。 例如,可以這樣做,以消除客戶端為不適用或可選的參數傳遞一個或多個null的需要。 為實現此目的而編寫的重載方法的示例包括Date類的構造函數,例如Date(int,int,int) , Date(int,int,int,int,int)和Date(int,int,int,int,int,int) ,int,int) 。
這種具有許多重載版本構造函數(每個構造函數都接受不同數量的參數)的方法稱為伸縮構造函數,并已被某些人稱為反模式 。 實際上,這種伸縮式構造方法的缺點是Josh Bloch專注于Effective Java第二版第2項中的Builder模式的驅動因素之一。 順便說一下, Date類還提供了一些重載的構造函數,它們也旨在實現上述目標,例如,允許從String構造Date 。
提供多個重載方法和構造函數以接受一組減少的必需或最低適用參數的想法可以應用于我們自己的類。 下一個代碼清單為原始方法提供了太多的參數,然后顯示了該方法的一些潛在的重載版本,這些版本接受減少的參數集。 為了便于討論,我們假設未在覆蓋的方法簽名之一中提供的任何參數是可選的,或不適用于該特定方法調用。 代碼注釋說明了每種方法如何做出某些假設以減少其參數數量。
方法過多且版本重載的參數示例
/*** Generates and provides an instance of the Person class. This method* expects all characteristics of the populated Person instance and so any* optional or not applicable characteristics must be passed in as null.* * @param lastName* @param firstName* @param middleName* @param salutation* @param suffix* @param streetAddress* @param city* @param state* @param isFemale* @param isEmployed* @param isHomeOwner* @return A Person object.*/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...}/*** Generate and provide an instance of the Person class that has only a first* and last name and address information. This method does not make any* assumptions about other characteristics of the instantiated Person, but* simply leaves those attributes undefined.* * @param lastName* @param firstName* @param streetAddress* @param city* @param state* @return Instance of Person class with no middle name and without specified* gender, employment status, or home ownership status.*/public Person createPerson(final String lastName,final String firstName,final String streetAddress,final String city,final String state){// implementation goes here...}/*** Generate and provide instance of Person class with no middle name and* with specified home ownership status. All instances of Person returned* from this method are assumed to be Female and to be Employed, but have no* address information.* * @param lastName* @param firstName* @param homeOwnerStatus* @return Instance of Person with provided first name, provided last name,* and provided home ownership status, and assumed to be an employed* female.*/public Person createPerson(final String lastName,final String firstName,final boolean homeOwnerStatus){// implementation goes here...}重載方法的Javadoc描述介紹了它們的不同方法。 第一種方法期望提供Person實例的所有特征,而對于不適用的參數,則需要提供null(例如,如果一個人沒有中間名,或者該中間名對于在此中的使用不重要)案件)。 第二個重載版本不希望提供所有參數,并假定它不希望的參數在返回的Person實例中仍未定義。
第三種重載方法版本大多是針對其特性未提供明確參數的假設。 例如,假設實例化的Person既是女性又是雇員。 第三種方法無法實例化男性或失業人員。 這說明了通過簡單的方法重載處理太多參數的缺點(僅根據參數的數量和類型重載具有相同名稱的方法)。
我在這篇文章中沒有顯示我自己的任何構造函數,但是同樣的問題和方法也適用于上述非構造函數方法。 同樣,重載的構造函數與重載的非構造函數方法具有相同的優點和缺點。
優勢與優勢
Java中的方法重載似乎很容易理解,并且在包括C / C ++和C#在內的多種語言中很常見。 當參數是可選的時,方法重載特別有效。 例如,在我的示例中,重載方法消除了傳遞中間名的期望,比重載方法假設特定實例是受雇女性要有效得多。 如果中間名,性別和就業狀況的特征確實是可選的,那么根本不假設任何一個值都比假設它們的特定值更好。
成本與劣勢
明智的方法重載可能很有用,但方法重載必須謹慎使用。 “ 學習Java語言 ” 課程的“ 類和對象”課程的“ 定義方法”部分警告:“應謹慎使用重載方法,因為它們會使代碼的可讀性大大降低。”
即使是我簡單的三個示例,也顯示了如何使重載很快變得難以閱讀。 在我的示例中,此代碼的閱讀者或用戶要么需要仔細閱讀Javadoc并相信它是最新且準確的,要么需要深入研究實現以查看該方法的每個重載版本的作用。 在IDE中,尤其是如果同一方法有許多重載版本,則很難確定哪種方法適用于給定的情況。
我的示例表明,必須使用注釋來解釋重載方法所做的假設。 如前所述,如果開發人員不費心地編寫它們,它們可能會過時,不準確甚至不可用。 能夠以不同的方式命名方法顯然更好,這樣方法的名稱可以提供有關其假設的線索,而不是僅依賴于Javadoc。 以這種方式使用命名方法將是以后的主題,但是根據定義為方法使用不同的名稱將使其不再重載。
我的示例顯示了使用帶有相同類型的多個參數的重載(同名)方法的特定限制。 第三個示例接受一個boolean ,但是只有Javadoc和該參數的名稱可以告訴我它適用于房屋所有權,而不適用于性別或就業狀況。 我無法提供類似的重載方法來使用相同的名稱信息和一個boolean ,該boolean表示不同的內容(例如性別或工作狀態),因為該方法與該boolean表示房屋所有權狀態的方法具有相同的簽名。 再次可以通過使用不同命名的方法來補救,這些方法指出了它們適用于哪種布爾條件。
解決此最后提到的限制的另一種方法是使用自定義類型和/或參數對象,并提供接受這些自定義類型的不同組合的重載方法的各種版本。 這在下一個代碼清單中與自定義類型一起顯示,該代碼顯示了對于這三個案例,當三個案例中的每個案例不需要共享同一類型時,如何通過單個第三個參數來重載接受兩個名稱字符串的方法。
自定義類型啟用改進的方法/構造函數重載
public Person createPerson(final String lastName,final String firstName,final HomeownerStatus homeOwnership){// implementation goes here...}public Person createPerson(final String lastName,final String firstName,final Gender gender){// implementation goes here...}public Person createPerson(final String lastName,final String firstName,final EmploymentStatus employmentStatus){// implementation goes here...}我要提到的最后一個缺點與使用方法重載來解決與方法或構造函數的參數過多有關的問題有關,這種方法將來可能導致大量的維護工作。 每當添加或刪除或什至更改該類的屬性(構造函數)或方法的參數,甚至可能需要單獨檢查并可能更改多個構造函數和/或方法。
結論
重載方法確實有其位置,并且可以是為客戶端提供更易理解和可讀的方法和構造函數的便捷方法。 但是,我發現這種方法是“最佳”方法,其頻率比已經介紹的其他方法( 自定義類型 , 參數對象 , 構建器 )少,甚至比我打算介紹的某些方法(例如不同的方法和方法)少。相同方法和構造函數的顯式命名版本)。 通過將方法重載與其他一些方法結合使用,可以減少方法重載方法的某些局限性和缺點。 例如, 自定義類型和參數對象的使用可以顯著提高一個人的能力,使其能夠更狹窄地定制重載方法或構造函數的各種版本,以使其符合要求。
翻譯自: https://www.javacodegeeks.com/2013/10/too-many-parameters-in-java-methods-part-4-overloading.html
總結
以上是生活随笔為你收集整理的Java方法中的参数太多,第4部分:重载的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 迪莫天赋洛克王国(洛克王国觉醒迪莫天赋)
- 下一篇: Java 8仍然需要LINQ吗? 还是比