java关于重载带来的难题—方法匹配

来源:互联网 发布:更改windows桌面路径 编辑:程序博客网 时间:2024/05/11 08:56

首先让我们来看一个例子(以下的输出结果基于jdk6版本):

class EasyOver {static void go(int x){System.out.println("int ");}static void go(long x){System.out.println("long ");}static void go(double x){System.out.println("double ");}public static void main(String[] args) {byte b = 5;short s = 5;long l = 5;float f = 5.0f;go(b);go(s);go(l);go(f);}}

对于上面的调用将会产生什么样的输出呢?相信对重载有一点了解的人可以很轻松的就写出输出结果:

intintlongdouble

这种结果我们一看就知道了,并且也不是那么令人惊讶,应为使用byte和short变元的调用被隐式加宽,以匹配带int的go()方法的版本,当然带long变元的调用会使用go()方法的long版本,最后,是用float变元的调用会与带double变元的方法匹配。

但是对于如下的带有装箱变元的go方法呢?

class AddBoxing{static void go(Integer x){System.out.println("Integer ");}static void go(long x){System.out.println("long");}public static void main(String args[]){int i = 4;go(i);}}

对于如上的代码将会产生怎样的输出呢?是Integer还是long呢?

正如我们所理解的那样,如果只存在go()方法的Integer变元,那么毫无疑问,java5的装箱能力将允许调用成功从而输出Integer;同样仅当long版本存在时,编译器将使用它处理go()方法调用,也就是会输出long,但是两个方法都存在,就像上面那样,编译器会使用哪个方法呢?

答案是:编译器将选择加宽而不是装箱,因此输出将是:

long
对于上面的结果,相信很多读者和我最初一样也有疑问,为什么呢???

对于这个问题,根据java5的设计者的解释是:最重要的规则应该是已有代码应该像他们过去那样运行,因此,既然加宽能力已经存在,通过加宽调用的方法不应该输给新创建的依赖于装箱的方法,基于这种规则,请预测下如下输出:

class AddVarargs{static void go(int x,int y){System.out.println("int,int");}static void go(byte... x){System.out.println("byte...");}public static void main(String args[]){byte b = 5;go(b,b);}}


相信聪明的你已经猜到输出是:

int,int

确实如你所想,即使每个调用都要求某种转换,在选择较新的风格之前,编译器仍将倾向于优先选择较老的风格,以保持现有代码的健壮性。

到这我们已经知道:

      1、 加宽将优于装箱先执行

      2、加宽优于var-arg(可变变元方法)执行

那么var-arg和装箱呢?请看下面的代码:

class BoxOrVararg {static void go(Byte x,Byte y){System.out.println("Byte,Byte");}static void go(byte... x){System.out.println("byte...");}public static void main(String[] args) {byte b = 4;go(b,b);}}

上面的结果将是什么呢?在这我就不说了,留给读者自己探索吧


另外,对于与基本数据类型对应的包装器类型之间是否也是这样的规律呢?

关于重载,还有几点比较重要,这篇就写到这了,我会在下一篇中继续介绍,欢迎大家来一起学习!

原创粉丝点击