1700438560
1700438561
我们知道Java编译器是很聪明的,它在编译时会根据方法签名(Method Signature)来确定调用哪个方法,比如calPrice(499900,75,95)这个调用,很明显75和95会被转成一个包含两个元素的数组,并传递到calPrice(int price, in..discounts)中,因为只有这一个方法签名符合该实参类型,这很容易理解。但是我们现在面对的是calPrice(49900,75)调用,这个“75”既可以被编译成int类型的“75”,也可以被编译成int数组“{75}”,即只包含一个元素的数组。那到底该调用哪一个方法呢?
1700438562
1700438563
我们先运行一下看看结果,运行结果是:
1700438564
1700438565
简单折扣后的价格是:¥374.25。
1700438566
1700438567
看来是调用了第一个方法,为什么会调用第一个方法,而不是第二个变长参数方法呢?因为Java在编译时,首先会根据实参的数量和类型(这里是2个实参,都为int类型,注意没有转成int数组)来进行处理,也就是查找到calPrice(int price, int discount)方法,而且确认它是否符合方法签名条件。现在的问题是编译器为什么会首先根据2个int类型的实参而不是1个int类型、1个int数组类型的实参来查找方法呢?这是个好问题,也非常好回答:因为int是一个原生数据类型,而数组本身是一个对象,编译器想要“偷懒”,于是它会从最简单的开始“猜想”,只要符合编译条件的即可通过,于是就出现了此问题。
1700438568
1700438569
问题是阐述清楚了,为了让我们的程序能被“人类”看懂,还是慎重考虑变长参数的方法重载吧,否则让人伤脑筋不说,说不定哪天就陷入这类小陷阱里了。
1700438570
1700438571
1700438572
1700438573
1700438575
编写高质量代码:改善Java程序的151个建议 建议5:别让null值和空值威胁到变长方法
1700438576
1700438577
上一建议讲解了变长参数的重载问题,本建议还会继续讨论变长参数的重载问题。上一建议的例子是变长参数的范围覆盖了非变长参数的范围,这次我们从两个都是变长参数的方法说起,代码如下:
1700438578
1700438579
public class Client{
1700438580
1700438581
public void methodA(String str, Integer……is){
1700438582
1700438583
}
1700438584
1700438585
public void methodA(String str, String……strs){
1700438586
1700438587
}
1700438588
1700438589
public static void main(String[]args){
1700438590
1700438591
Client client=new Client();
1700438592
1700438593
client.methodA(“China”,0);
1700438594
1700438595
client.methodA(“China”,“People”);
1700438596
1700438597
client.methodA(“China”);
1700438598
1700438599
client.methodA(“China”,null);
1700438600
1700438601
}
1700438602
1700438603
}
1700438604
1700438605
两个methodA都进行了重载,现在的问题是:上面的代码编译通不过,问题出在什么地方?看似很简单哦。
1700438606
1700438607
有两处编译通不过:client.methodA(“China”)和client.methodA(“China”,null),估计你已经猜到了,两处的提示是相同的:方法模糊不清,编译器不知道调用哪一个方法,但这两处代码反映的代码味道可是不同的。
1700438608
1700438609
对于methodA(“China”)方法,根据实参“China”(String类型),两个方法都符合形参格式,编译器不知道该调用哪个方法,于是报错。我们来思考这个问题:Client类是一个复杂的商业逻辑,提供了两个重载方法,从其他模块调用(系统内本地调用或系统外远程调用)时,调用者根据变长参数的规范调用,传入变长参数的实参数量可以是N个(N>=0),那当然可以写成client.methodA(“china”)方法啊!完全符合规范,但是这却让编译器和调用者都很郁闷,程序符合规则却不能运行,如此问题,谁之责任呢?是Client类的设计者,他违反了KISS原则(Keep It Simple, Stupid,即懒人原则),按照此规则设计的方法应该很容易调用,可是现在在遵循规范的情况下,程序竟然出错了,这对设计者和开发者而言都是应该严禁出现的。
[
上一页 ]
[ :1.70043856e+09 ]
[
下一页 ]