建议 4:避免带有边长参数的方法重载

在项目和系统开发中,为了提高方法的灵活度和可复用性,我们经常要传递不确定数量的参数到方法中,在Java5之前常用的设计技巧就是把形参定义成collection类型或其子类类型,或者数组类型,这种方法的缺点就是徐要对空参数进行判断和筛选,比如实参为null值和长度为0的collection或数组。而Java5引入边长参数(varags)就是为了更好地提高方法的复用性,让方法的调用者可以“随心所欲”地传递实参数量,当然边长参数也是要遵循一定规则的,比如边长参数必须是方法中的最后一个参数;一个方法不能定义多个边长参数等,这些基本规则需要牢记,但是即使记住了这些规则,仍然有可能出现错误,我们一块来看下代码:

public class Client {
    
    //简单折扣计算
    public void calPrice(int price,int discount){
        float knockdownPrice =price * discount / 100.0F;
        System.out.println("简单折扣后的价格是:"+formateCurrency(knockdownPrice));
    }
    
    //复杂多折扣计算
    public void calPrice(int price,int... discounts){
        float knockdownPrice = price;
        for(int discount:discounts){
            knockdownPrice = knockdownPrice * discount / 100;
        }
        System.out.println("复杂折扣后的价格是:" +formateCurrency(knockdownPrice));
    }
    
    //格式化成本地货币形式
    private String formateCurrency(float price){
        return NumberFormat.getCurrencyInstance().format(price/100);
    }
    
    public static void main(String[] args) {
        Client client = new Client();
        //499元的货物,打75折
        client.calPrice(49900, 75);
    }
}

这是一个计算商品价格折扣的模拟类,带有两个参数的calPrice方法(该方法的业务逻辑是:提供商品的原价和折扣率,即可获得商品的折扣价)是一个简单的折扣计算方法,该方法在实际项目中经常会用到,这是一个单一的打折方法。而带有边长参数的calPrice方法则是较复杂的折扣计算方式,多种折扣的叠加运算(模拟类是一种比较简单的实现)在实际生活中也是经常见到的比如在大甩卖期间对VIP会员再度进行打折;满100折扣9.5折当满500直减100;生日当天在原有折扣上再给一个8折优惠等。
业务逻辑已经比较清楚了,我们来仔细看一下这两个方法,他们是重载吗?自然是的,重载的定义是:“方法名相同,参数类型或数量不同”,很明显这两个方法是重载。但是在仔细一看这两个方法重载的有点特殊:calPrice(int price,int...discounts)的参数范畴覆盖了calPrice(int price,int...discount)的参数范畴。那问题就出来了对于calPrice(49900,75)这样的计算,到底该 调用那个方法来处理呢?
我们知道Java编译器是很聪明的,他在编译时会根据方法签名(Method Signature)来确定调用那个方法,比如calPrice(int price,int...discounts)中,因为只有这一个方法签名符合该实参类型,这很容易理解。但是我们现在面对的是calPrice(49900,75)调用,这个“75”既可以被编译成int类型的“75”,也可以被编译成int数组“{75}”,即只包含一个元素的数组。到底该调用哪一个方法呢?
简单折扣后的价格是:$374.25。
看来是调用了第一个方法,为什么是第一个方法呢?因为Java在编译时,首先会根据实参的数量和类型(这里是两个实参,都是int类型,注意没有转成int数组)来进行处理,也就是查到calPrice(int price,int...discount)方法,而且确认它是否符合方法签名条件。现在的问题是编译器为什么会首先根据两个int类型的实参而不是1个int类型,1个数组类型的实参来查找方法呢?
因为int是一个原生数据类型,而数组本身是一个对象,编译器想要“偷懒”,于是他会从最简单的开始“猜想”,只要符合编译条件的即可通过。
所以,大家在使用这些参数方法的时候要注意考虑哦!想一下机器是怎么执行的。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值