[b][color=red][size=medium]本文版权归作者所有,仅供用来网上学习来用,读者可以收藏,请不要下载到本机和重新发布到其它网站[/size][/color][/b]
在Java 中,同一个类中的2个或2个以上的方法可以有同一个名字,只要它们的参数声明不同即可。在这种情况下,该方法就被称为重载(overloaded ),这个过程称为方法重载(method overloading )。
这篇文章不是为了讲什么是重载,怎么重载,而是为了举例重载时的一种特殊情况。
上面也说了,重载是方法名同,而参数的声明不同。参数的声明不同不包括参数名不同,而是参数的类型不同。下面给出几种正确的方法重载的例子:
从上面的代码可以看出,这几个test方法名称不用说都是相同的,但参数列表不同。前三个test方法的重载是因为参数的个数不同。第三个和第四个test方法,第五个和第六个test方法是因为参数的类型不同。而第三个和第五个,第四个和第六个是因为参数的位置不同。因些参数声明不同包括参数的个数,参数的类型,参数的顺序,但不包括参数名不同。像下面这种形式是错误的,不仅不是重载,连编译也不会通过,因为这两个方法其实是同一个方法。
我们来看第一个方法执行的结果,首先我们写一个main方法来做个测试,分别调用这几个方法。有一点说明,测试是基于JRE5.0以后的版本。这时,由于JRE支持int和Integer类型的自动转换,这样的重载很容易出BUG。
在写这个测试方法之前,我们先看一个关于基本数据类型和其封装类自动转换的例子,这一内容会在后面的文章中专门写。
结果是:
0
1
2
从结果上看,当程序执行到第8行时,发现i0为int类型,而方法的参数需要的是Integer类型,JVM会把i0自动转换成Integer,然后执行test(Integer)方法。
看完上面的自动类型转换的小例子,再看第一个例子的测试方法
程序执行的结果是:
test()
test(String)
test(String, int)
test(String, Integer)
test(int, String)
test(Integer, String)
很明显,JRE会按照最精确匹配上的方法执行。JVM在执行过程中,会首先去匹配最精确匹配的方法,如果不能找,则寻找可进行自动类型转换后能匹配上的方法。
这个过程如果程序员不注意的话,很容易出现错误,尤其是有继承关系的时候,重载父类的方法容易出错,到时只好DEBUG来查了。
再看一下之方面的例子:
结果是:
test(int)
test(Integer)
test(String)
test(Object)
test(Object)
程序的第13行和第14行值得注意,obj1和obj2显然是Integer类型的,但是引用类型却是Object类型,JVM不会因为对象的真实类型是Integer类型,而去选择执行test(Integer),而是根据其引用类型Object选择了test(Object)。因为引用类型的自动转换只能从子类向其父类或父接口转换。
像这样继承结构比较复杂的系统中,注意重载时的参数的类型自动转换,不然很容易会出现意想不到的结果。
在Java 中,同一个类中的2个或2个以上的方法可以有同一个名字,只要它们的参数声明不同即可。在这种情况下,该方法就被称为重载(overloaded ),这个过程称为方法重载(method overloading )。
这篇文章不是为了讲什么是重载,怎么重载,而是为了举例重载时的一种特殊情况。
上面也说了,重载是方法名同,而参数的声明不同。参数的声明不同不包括参数名不同,而是参数的类型不同。下面给出几种正确的方法重载的例子:
public class OverloadEx {
public static void test() {
System.out.println("test()");
}
public static void test(String arg) {
System.out.println("test(String)");
}
public static void test(String arg0, int arg1) {
System.out.println("test(String, int)");
}
public static void test(String arg0, Integer arg1) {
System.out.println("test(String, Integer)");
}
public static void test(int arg0, String arg1) {
System.out.println("test(int, String)");
}
public static void test(Integer arg0, String arg1) {
System.out.println("test(Integer, String)");
}
}
从上面的代码可以看出,这几个test方法名称不用说都是相同的,但参数列表不同。前三个test方法的重载是因为参数的个数不同。第三个和第四个test方法,第五个和第六个test方法是因为参数的类型不同。而第三个和第五个,第四个和第六个是因为参数的位置不同。因些参数声明不同包括参数的个数,参数的类型,参数的顺序,但不包括参数名不同。像下面这种形式是错误的,不仅不是重载,连编译也不会通过,因为这两个方法其实是同一个方法。
public static void test(String arg00, int arg01);
public static void test(String arg10, int arg11);
我们来看第一个方法执行的结果,首先我们写一个main方法来做个测试,分别调用这几个方法。有一点说明,测试是基于JRE5.0以后的版本。这时,由于JRE支持int和Integer类型的自动转换,这样的重载很容易出BUG。
在写这个测试方法之前,我们先看一个关于基本数据类型和其封装类自动转换的例子,这一内容会在后面的文章中专门写。
public class AutoTypeTrans {
public static void main(String[] args) {
int i0 = 0;
Integer i1 = 1;
Integer i2 = new Integer(2);
test(i0);
test(i1);
test(i2);
}
public static void test(Integer integer) {
System.out.println(integer);
}
}
结果是:
0
1
2
从结果上看,当程序执行到第8行时,发现i0为int类型,而方法的参数需要的是Integer类型,JVM会把i0自动转换成Integer,然后执行test(Integer)方法。
看完上面的自动类型转换的小例子,再看第一个例子的测试方法
public static void main(String[] args) {
int i = 10;
Integer integer = i;
String s = "test";
test();
test(s);
test(s, i);
test(s, integer);
test(i, s);
test(integer, s);
}
程序执行的结果是:
test()
test(String)
test(String, int)
test(String, Integer)
test(int, String)
test(Integer, String)
很明显,JRE会按照最精确匹配上的方法执行。JVM在执行过程中,会首先去匹配最精确匹配的方法,如果不能找,则寻找可进行自动类型转换后能匹配上的方法。
这个过程如果程序员不注意的话,很容易出现错误,尤其是有继承关系的时候,重载父类的方法容易出错,到时只好DEBUG来查了。
再看一下之方面的例子:
public class InheritOverload {
public static void main(String[] args) {
int i = 0;
Integer integer = new Integer(1);
String s = "2";
Object obj1 = integer;
Object obj2 = 4;
Sub sub = new Sub();
sub.test(i);
sub.test(integer);
sub.test(s);
sub.test(obj1);
sub.test(obj2);
}
}
class Base {
public void test(int arg) {
System.out.println("test(int)");
}
public void test(Object arg) {
System.out.println("test(Object)");
}
}
class Sub extends Base {
public void test(Integer arg) {
System.out.println("test(Integer)");
}
public void test(String arg) {
System.out.println("test(String)");
}
}
结果是:
test(int)
test(Integer)
test(String)
test(Object)
test(Object)
程序的第13行和第14行值得注意,obj1和obj2显然是Integer类型的,但是引用类型却是Object类型,JVM不会因为对象的真实类型是Integer类型,而去选择执行test(Integer),而是根据其引用类型Object选择了test(Object)。因为引用类型的自动转换只能从子类向其父类或父接口转换。
像这样继承结构比较复杂的系统中,注意重载时的参数的类型自动转换,不然很容易会出现意想不到的结果。