Java的重载的类型匹配

[b][color=red][size=medium]本文版权归作者所有,仅供用来网上学习来用,读者可以收藏,请不要下载到本机和重新发布到其它网站[/size][/color][/b]

在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)。因为引用类型的自动转换只能从子类向其父类或父接口转换。
像这样继承结构比较复杂的系统中,注意重载时的参数的类型自动转换,不然很容易会出现意想不到的结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值