[改善Java代码]避免带有变长参数的方法重载
建议4: 避免带有变长参数的方法重载
在项目和系统的开发中,为了提高方法的灵活度和可复用性,我们经常要传递不确定数量的参数到方法中,在Java 5之前常用的设计技巧就是把形参定义成Collection类型或其子类类型,或者是数组类型,这种方法的缺点就是需要对空参数进行判断和筛选,比如实参为null值和长度为0的Collection或数组。
而 Java 5引入变长参数(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){
knockdownPriceknockdownPrice = 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);
}
}
运行结果:
简单折扣后的价格是:¥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编译器的"最短路径原则":如果能够在本类中查找到的变量,常量,方法,就不会到其他包或父类,接口中查找,以确保本类中的属性方法优先.
[改善Java代码]避免带有变长参数的方法重载的更多相关文章
- [改善Java代码]覆写变长方法也循规蹈矩
建议6:覆写变长方法也循规蹈矩 在Java中,子类覆写父类中的方法很常见,这样做既可以修正Bug也可以提供扩展的业务功能支持,同时还符合开闭原则(Open-Closed Principle),我们来看 ...
- Java中可变长参数的方法
原文转自:http://www.cnblogs.com/lanxuezaipiao/p/3190673.html 在Java5 中提供了变长参数(varargs),也就是在方法定义中可以使用个数不确定 ...
- Java Filter过滤xss注入非法参数的方法
http://blog.csdn.NET/feng_an_qi/article/details/45666813 Java Filter过滤xss注入非法参数的方法 web.xml: <filt ...
- JavaSE 可变参数的方法重载
/** * 可变参数的方法重载 */ class A { public void test(int a, int b) { System.out.println(a+", "+b) ...
- [改善Java代码]避开基本类型数组转换列表陷阱
开发中经常用到Arrays和Collections这两个工具类. 在数组和列表之间进行切换.非常方便.但是也会遇到一些问题. 看代码: import java.util.Arrays; import ...
- [改善Java代码]强制声明泛型的实际类型
Arrays工具类有一个方法asList可以把一个变长参数或数组变成列表,但是它有一个缺点:它所生成的List长度是不可改变的,而这在我们的项目开发中很不方便. import java.util.Ar ...
- [改善Java代码]asList方法产生的List对象不可更改
上一个建议之处了asList方法在转换基本类型数组时候存在的问题,在看下asList方法返回的列表有何特殊的地方.看代码: import java.util.Arrays; import java.u ...
- [改善Java代码]动态加载不适合数组
上一个建议解释了为什么要使用forName,本建议就说说哪些地方不适合使用动态加载. 如果forName要加载一个类,那它必须是一个类------8中基本类型就排除在外.它们不是一个具体的类. 其次它 ...
- [改善Java代码]Java的泛型是类型擦除的
泛型可以减少强制类型的转换,可规范集合的元素类型,还可以提高代码的安全性和可读性,正是因为有了这些优点,自从Java引入泛型之后,项目的编码规则上便多了一条,优先使用泛型. Java泛型(Generi ...
随机推荐
- Spring入门(3)-Spring命名空间与Bean作用域
Spring入门(3)-Spring命名空间与Bean作用域 这篇文章主要介绍Spring的命名空间和Bean作用域 0. 目录 Spring命名空间 Bean作用域 1. Spring命名空间 在前 ...
- [iOS 多线程 & 网络 - 2.1] - 解析json
A.iOS中json的基本使用 1.解析json数据 (1)json反序列化 对象{}格式 {key : value, key : value,...} 的键值对的结构可以反序列化为OC中的NSDic ...
- List、ArrayList、Vector及map、HashTable、HashMap分别的区别
一.List与ArrayList的区别 List->AbstractList->ArrayList (1) List是一个接口,ArrayList是一个实现了List接口 ...
- MVC 中WebViewPage的运用
MVC在View的最后处理中是将View的文件页面编译成一个类,这个类必须继承自WebViewPage,WebViewPage默认添加对AjaxHelper和HtmlHelper的支持 public ...
- Hadoop on Mac with IntelliJ IDEA - 1 解决input path does not exist问题
本文讲述使用IntelliJ IDEA时遇到Hadoop提示input path does not exist(输入路径不存在)的解决过程. 环境:Mac OS X 10.9.5, IntelliJ ...
- synthesize(合成) keyword in IOS
synthesize creates setter and getter (从Objective-C 2.0开始,合成可自动生成存取方法) the setter is used by IOS to s ...
- Windbg命令
(1)!runaway命令显示每个线程消费的时间 参考:http://blog.csdn.net/hgy413/article/details/7564252 (2)!wow64exts.sw 关闭6 ...
- delphi HTML代码
################################属性 设置################################################字体设置{//-------- ...
- Centos 6.5使用Bumblebee关闭N卡,冷却你的电脑
夏天来了,笔记本装的Centos一直非常热.随着天气的变化,这个问题真的要攻克了.差了下原因可能是双显卡笔记本,N卡驱动不完好,导致风扇狂叫. 昨天安装了nvidia 的显卡驱动本以为时间安静了.但是 ...
- 清除XCode缓存和生成文件
1.Command-Option-Shift-K to clean out the build folder XCode4.2 finder中找到 /Users/apple/Library/ ...