[改善Java代碼]避免帶有變長參數的方法重載


建議4: 避免帶有變長參數的方法重載

在項目和系統的開發中,為了提高方法的靈活度和可復用性,我們經常要傳遞不確定數量的參數到方法中,在Java 5之前常用的設計技巧就是把形參定義成Collection類型或其子類類型,或者是數組類型,這種方法的缺點就是需要對空參數進行判斷和篩選,比如實參為null值和長度為0的Collection或數組。

而 Java 5引入變長參數(varags)就是為了更好地提高方法的復用性,讓方法的調用者可以“隨心所欲”地傳遞實參數量,當然變長參數也是要遵循一定規則的,

比如變長參數必須是方法中的最后一個參數;一個方法不能定義多個變長參數等,這些基本規則需要牢記,但是即使記住了這些規則,仍然有可能出現錯誤,我們來看如下代碼:

 1 public class Client {     
 2      //簡單折扣計算  
 3      public void calPrice(int price,int discount){  
 4            float knockdownPrice =price * discount / 100.0F;  
 5            System.out.println("簡單折扣后的價格是:"+formateCurrency(knockdownPrice));  
 6      }    
 7      //復雜多折扣計算  
 8      public void calPrice(int price,int... discounts){  
 9            float knockdownPrice = price;  
10            for(int discount:discounts){  
11                    knockdownPriceknockdownPrice = knockdownPrice * discount / 100;  
12         }  
13         System.out.println("復雜折扣后的價格是:" +formateCurrency(knockdownPrice));  
14      }  
15      //格式化成本的貨幣形式  
16      private String formateCurrency(float price){  
17             return NumberFormat.getCurrencyInstance().format(price/100);  
18      }  
19       
20      public static void main(String[] args) {  
21            Client client = new Client();  
22            //499元的貨物,打75折  
23            client.calPrice(49900, 75);  
24     }  
25 } 

運行結果:

簡單折扣后的價格是:¥374.25

這是一個計算商品價格折扣的模擬類,帶有變長參數的calPrice方法則是較復雜的折扣計算方式,多種折扣的疊加運算(模擬類是一種比較簡單的實現)在實際生活中也是經常見到的,比如在大甩賣期間對VIP會員再度進行打折;或者當天是你的生日,再給你打個9折,也就是俗話說的“折上折”。

兩個calPrice()方法重載有點特殊:calPrice(int price,int... discounts)的參數范疇覆蓋了calPrice(int price,int discount)的參數范疇。那問題就出來了:對於calPrice(49900,75)這樣的計算,到底該調用哪個方法來處理呢?

從運行結果來看是調用了第一個方法,而不是變長參數的方法.

因為Java在編譯時,首先會根據實參的數量和類型(這里是2個實參,都為int類型,注意沒有轉成int數組)來進行處理,也就是查找到calPrice(int price,int discount)方法,而且確認它是否符合方法簽名條件。現在的問題是編譯器為什么會首先根據2個int類型的實參而不是1個int類型、1個int數組類型的實參來查找方法呢?這是個好問題,也非常好回答:因為int是一個原生數據類型,而數組本身是一個對象,編譯器想要“偷懶”,於是它會從最簡單的開始“猜想”,只要符合編譯條件的即可通過,於是就出現了此問題。

問題是闡述清楚了,為了讓我們的程序能被“人類”看懂,還是慎重考慮變長參數的方法重載吧,否則讓人傷腦筋不說,說不定哪天就陷入這類小陷阱里了。

 

//============================================

這里說一個Java編譯器的"最短路徑原則":如果能夠在本類中查找到的變量,常量,方法,就不會到其他包或父類,接口中查找,以確保本類中的屬性方法優先.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM