zoukankan      html  css  js  c++  java
  • [改善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编译器的"最短路径原则":如果能够在本类中查找到的变量,常量,方法,就不会到其他包或父类,接口中查找,以确保本类中的属性方法优先.

  • 相关阅读:
    linux下运行、停止jar包
    .net开发CAD2008无法调试的解决方法
    【转】C#获取当前程序运行路径的方法集合
    如何在arcmap中调试addin或者插件
    【转】WriteMessage的信息在AutoCAD中命令行中实时显示
    ArcGIS10的附件功能
    CAD调试时抛出“正试图在 os 加载程序锁内执行托管代码。不要尝试在 DllMain 或映像初始化函数内运行托管代码”异常的解决方法
    [转]Tesseract 3.02中文字库训练
    Truncated incorrect DOUBLE value
    tomcat无故停止
  • 原文地址:https://www.cnblogs.com/DreamDrive/p/5412359.html
Copyright © 2011-2022 走看看