4.1.2 方法的输入参数
对于方法的输入参数来说,还有几个值得注意的地方,接下来分别对输入参数的几种用法加以阐述。一个方法可以有输入参数,也可以没有输入参数,倘若无须输入参数,则方法定义的圆括号内部直接留空。以打印当前时间为例,下面的showTime方法没有输入参数也能实现(完整代码见本章源码的src\com\method\function\Input.java):
// 若没有输入参数,则方法名称后面的圆括号内部留空。showTime方法的用途是显示当前时间 private static void showTime() { Date date=new Date(); // 创建一个时间实例 int hour=date.getHours(); // 获取当前时钟 int minute=date.getMinutes(); // 获取当前分钟 int second=date.getSeconds(); // 获取当前秒钟 System.out.println("当前时间是"+hour+"时"+minute+"分"+second+"秒"); }
在main方法里面只要以下简单的一行代码,即可调用showTime方法,成功运行showTime内部的时间打印代码:
showTime(); // 显示当前时间
当然,方法定义的多数情况是存在输入参数的,并且参数格式为“参数类型参数名称”。像闹钟的设置操作,就必须输入闹钟提醒的时分秒,或者设定闹钟在当前时刻之后的某个时间触发。于是形成了以下的setAlarm方法,该方法准备延迟若干小时后打印日志:
// 只有一个输入参数,参数格式为“参数类型 参数名称” // setAlarm方法的用途是设置指定时刻的闹钟,其中时钟为在当前时间上增加若干小时 private static void setAlarm(int addedHour) { Date date=new Date(); // 创建一个时间实例 int hour=date.getHours()+addedHour; // 给当前时钟加上若干小时 int minute=date.getMinutes(); // 获取当前分钟 int second=date.getSeconds(); // 获取当前秒钟 System.out.println("设定的闹钟时间是"+hour+"时"+minute+"分"+second+"秒"); }
如需设定闹钟在一个小时后触发,则调用setAlarm方法时填写参数1,代码如下:
setAlarm(1); // 设置一小时之后的闹钟
若想输入多个参数,则在圆括号内通过逗号来分隔参数列表。例如下面的setAlarm方法,支持同时输入小时数和分钟数:
// 有两个输入参数,参数格式为“参数1类型 参数1名称, 参数2类型 参数2名称” // 下面的setAlarm方法与上面的setAlarm方法名称相同,但参数个数不同,该情况被称作方法重载 // 虽然两个方法的方法名称一样,但是编译器能够根据参数个数和参数类型来判断要调用哪个方法 private static void setAlarm(int addedHour, int addedMinute) { Date date=new Date(); // 创建一个时间实例 int hour=date.getHours()+addedHour; // 给当前时钟加上若干小时 int minute=date.getMinutes()+addedMinute; // 给当前分钟加上若干分钟 int second=date.getSeconds(); // 获取当前秒钟 System.out.println("设定的闹钟时间是"+hour+"时"+minute+"分"+second+"秒"); }
注意到带两个参数的setAlarm方法和带一个参数的setAlarm方法居然同名,为什么变量不能重名,方法却能重名呢?这是因为两个方法的参数个数不一样,即使代码里的方法名称看起来相同,其实编译器会偷偷给它们改名。比如只带一个参数的setAlarm方法,编译器给它的编号可能是setAlarm_1;而带两个参数的setAlarm方法,编译器可能给它分配编号setAlarm_2。所以只要参数个数不同或者参数类型不同,代码中的同名方法都会被编译器当作不同的方法,这种情况也称作“方法重载”。
有了方法重载,再添加第三个、第四个参数,也能通过重载同名方法来实现。可是如此一来,方法数量就多了许多,有没有一种机制能够动态调整参数的个数呢?有,该机制在Java中叫作可变参数,意思是参数的个数是允许变化的,只要这些参数的类型保持一致即可。仍旧以闹钟为例,提醒的时间单位时、分、秒分别对应3个整型参数,那么完全可以定义整型的可变参数,参数的数量可多可少,有几个参数就用几个参数。Java的参数“可变”符号利用变量类型后面的三个点号“...”来表示,比如“int...”表示整型的可变参数,而“double...”表示双精度型的可变参数。于是采用了可变参数的setAlarm方法便改写成下面这样:
// 参数类型后面添加三个点号“…”,表示这里的参数数量并不固定,可以有一个、两个,也可以有三个,也可以没有参数。因此此时的输入参数被称为可变参数,意思是参数的数量允许变化,“…”可以看作是方法参数的省略号 private static void setAlarm(int... addedNumber) { Date date=new Date(); // 创建一个时间实例 int hour=date.getHours(); // 获取当前时钟 int minute=date.getMinutes(); // 获取当前分钟 int second=date.getSeconds(); // 获取当前秒钟 // 可变参数的数量也是通过“.length”获得的 if (addedNumber.length > 0) { // 至少有一个输入参数 // 获取指定位置的可变参数,依然通过下标“[数字]”实现,就像是访问数组元素一般 hour += addedNumber[0]; } if (addedNumber.length > 1) { // 至少有两个输入参数 minute += addedNumber[1]; } if (addedNumber.length > 2) { // 至少有三个输入参数 second += addedNumber[2]; } System.out.println("可变参数设定的闹钟时间是"+hour+"时"+minute+"分"+second+"秒"); }
外部调用带可变参数的方法时,既允许不输入任何参数,又允许输入多个参数。以下即为拥有可变参数的setAlarm方法的调用代码例子:
setAlarm(); // 带可变参数的方法允许没有输入参数 setAlarm(1, -10, 3); // 带可变参数的方法允许有多个输入参数
注意,若已经存在同名且参数个数确定的方法,则编译器优先调用参数个数确定的方法。只有不存在参数个数确定的同名方法,编译器才会调用定义了可变参数的方法。
输入参数的类型还可以是数组,例如整型数组的参数定义格式为“int[]参数名称”,这样方法内部就会将该参数当作数组一样操作。使用了数组参数的闹钟设置方法setAlarmByArray代码示例如下:
// 编译器认为“int...”与“int[] ”类型相同,所以不允许定义参数为“int...”和“int[] ”的同名方法 private static void setAlarmByArray(int[] addedNumber) { Date date=new Date(); // 创建一个时间实例 int hour=date.getHours(); // 获取当前时钟 int minute=date.getMinutes(); // 获取当前分钟 int second=date.getSeconds(); // 获取当前秒钟 if (addedNumber.length > 0) { // 数组大小大于0 hour += addedNumber[0]; } if (addedNumber.length > 1) { // 数组大小大于1 minute += addedNumber[1]; } if (addedNumber.length > 2) { // 数组大小大于2 second += addedNumber[2]; } System.out.println("设定的闹钟时间是"+hour+"时"+minute+"分"+second+"秒"); }
可见该方法的内部代码竟然与采用可变参数的setAlarm代码是一样的,这缘于编译器把“int...”和“int[]”看作是同一种类型,既然是同一种类型,那么这两个方法就不能叫一样的名称,只能换别的名称才行。此外,二者被外部调用时也有差别,带可变参数的方法调用时输入的参数列表以逗号分隔;而带数组参数的方法,它的输入参数必须是数组类型,就像下面的调用代码例子一样:
int[] addedArray={1, -10, 3}; setAlarmByArray(addedArray); // setAlarmByArray方法的输入参数为数组类型
至此,终于把方法的几种输入参数变化讲完了。最后总结一下与输入参数有关的几个要点:
(1)名称相同,但是参数个数与参数类型不同的方法,是通过方法重载机制区分开的。
(2)输入参数在变量类型后面添加三点号“...”,表示这个输入参数是可变参数,调用时填写的参数数量可多可少。
(3)可变参数与数组参数在方法内部的处理代码基本没有区别,但在外部调用时书写的参数形式是不一样的。