方法重载(method overloading).在Java中,同一个类中的两个或多个方法可以共享一个名称,只要他们的形参声明不一样就可以.当这种情况发生时,就称方法被重载(overloaded)了,而这一过程也就称为方法重载.方法重载是Java实现多态性的途径之一.
总之,重载一个方法只需要声明他的几个不同版本就可以,其余的交给编译器处理即可.必须注意如下重要限制:每个被重载的方法的形参类型和数量必须不同,两个方法仅仅返回类型不一样是不够的(返回类型无法在所有情况下为Java提供足够的信息来确定使用哪个方法).当然,被重载的方法的返回来信也可以是不一样的.当调用被重载的方法时,将执行形参与实参相匹配的那个方法.
下面的示例对方法重载进行了说明:
public class test2 { // @param args public static void main(String args[]) { Overload obj = new Overload(); obj.method(); obj.method(1, 2); } } class Overload { void method() { System.out.println("no parameters"); } void method(int a) { System.out.println("one parameters"); } void method(int a,int b) { System.out.println("two parameters"); } }
输出:
no parameters two parameters
如你所见,method被重载了3次,第一个版本没有形参,第二个版本有一个整型形参,第三个版本有两个整型形参.这几个版本都是有效的,然而如前所述,无论方法返回的类型是什么,都与能够重载无关,因此,使用下面的两个版本的method()将会导致错误发生:
void method(int a) { System.out.println("one parameters"); } int method(int a) { System.out.println("one parameters"); return 1; }
只有返回类型不同而进行重载是不行的.
Java提供的某些自动类型转换,这些转换也可以应用于重载方法的形参:
public class test2 { // @param args public static void main(String args[]) { Overload2 ob = new Overload2(); int i = 10; double d = 10.1; byte b = 99; short s = 10; float f = 11.5F; ob.f(i); ob.f(d); ob.f(b); ob.f(s); ob.f(f); } } class Overload2 { void f(int x) { System.out.println("Inside f(int) "+x); } void f(double x) { System.out.println("Inside f(double) "+x); } }
输出:
Inside f(int) 10 Inside f(double) 10.1 Inside f(int) 99 Inside f(int) 10 Inside f(double) 11.5
在本例中,只定义了两个版本的f(),第一个版本有一个int形参,第二个版本有一个double形参.然而也可以向f()传递byte,short或float值.传递byte类型和short类型时,Java会自动将他们转换int类型,因此就会调用f(int).在传递float类型时,该值就会转换为double类型,所以会调用f(double).
自动转换只能在形参和实参之间不能直接匹配时使用,理解这一点很重要.例如,在上述程序的基础上再定义一个使用byte形参的f()版本,如下所示:
public class test2 { // @param args public static void main(String args[]) { Overload2 ob = new Overload2(); int i = 10; double d = 10.1; byte b = 99; short s = 10; float f = 11.5F; ob.f(i); ob.f(d); ob.f(b); ob.f(s); ob.f(f); } } class Overload2 { void f(int x) { System.out.println("Inside f(int) "+x); } void f(byte x) { System.out.println("Inside f(byte) "+x); } void f(double x) { System.out.println("Inside f(double) "+x); } }
输出:
Inside f(int) 10 Inside f(double) 10.1 Inside f(byte) 99 Inside f(int) 10 Inside f(double) 11.5
本例中,因为有一个版本的f()使用了byte实参,所以当使用byte实参来调用f()时,就会调用f(byte),不会再自动转换为int类型.
方法重载支持多态性,因为他是Java的实现”单接口,多方法”的途径之一.考虑下面的内容,就会理解其中的原因.在不支持方法重载的语言中,每一种方法必须被赋予唯一的名称.然而,你可能经常会对不同类型的数据实现本质上相同的方法.考虑下绝对值函数.在不支持方法重载的语言中,绝对值函数经常会有三个或更多个版本,每一个都有一个略微不同的名称.例如,在C语言中,函数abs()返回整数的绝对值,labs()返回长整数的绝对值,而fabs()返回浮点数的绝对值.因为C语言不支持重载,所以每一个函数不得不拥有自己的名称,尽管这三个函数本质上完成的功能是一样的.这样一来就使得情况在概念上变得比实际更复杂了.尽管每个函数内在的概念是一致的,但依然需要记住三个函数名.而这种情况在Java中就不会出现,因为每一个绝对值方法都可以使用同一个名称.实际上,Java的标准类库就包含一个名为abs()的绝对值方法.该方法被Java的Math类重载以处理不同的数值类型.Java根据实参的类型来决定调用何种版本的abs().
重载的价值在于允许使用同一个名称来访问相关的方法.因此,名称abs()代表的是要执行的一般动作,而根据特定的环境选择正确版本的任务则可以交给编译器来完成.作为程序员,只需要记住要执行的一般操作即可.通过应用的多态性,若干个名称即可减少到一个.尽管这个示例相当简单,但是如果把这一概念扩展开来,就会发现重载对于管理更为复杂的程序会起到多么大的作用.
当重载一个方法时,该方法的每一个版本都可以执行你所期望的任意活动.虽然被重载的方法之间彼此可以不相关,然而从形式上讲,方法重载就意味着一种关系的存在.因此,尽管可以使用同一个名称重载无关的方法,但是最好不要这样做.例如,尽管可以使用名称sqr创建方法来返回整数的平方和浮点数的平方根,但是这两种运算根本不同.以这种方式应用方法重载就违背了他的初衷.在实际应用中,应该只重载紧密相关的操作.
问:”签名”这个术语,他指的是什么?
答:在Java中,签名(signature)指的是方法名及其形参列表.因此,在重载时,一个类中的两个方法不能具有相同的签名.注意,签名不包含返回类型,因为Java不使用签名进行重载解析.