1700440724
1700440725
基本类型的方法被调用
1700440726
1700440727
基本类型的方法被调用
1700440728
1700440729
cilent. f(i)的输出是正常的,我们已经解释过了。那第二个输出就让人很困惑了,为什么会调用f(long a)方法呢?这是因为自动装箱有一个重要的原则:基本类型可以先加宽,再转变成宽类型的包装类型,但不能直接转变成宽类型的包装类型。这句话比较拗口,简单地说就是,int可以加宽转变成long,然后再转变成Long对象,但不能直接转变成包装类型,注意这里指的都是自动转换,不是通过构造函数生成。为了解释这个原则,我们再来看一个例子:
1700440730
1700440731
public class Client{
1700440732
1700440733
public static void main(String[]args){
1700440734
1700440735
int i=100;
1700440736
1700440737
f(i);
1700440738
1700440739
}
1700440740
1700440741
public static void f(Long l){
1700440742
1700440743
}
1700440744
1700440745
}
1700440746
1700440747
这段程序编译是通不过的,因为i是一个int类型,不能自动转变为Long型。但是修改成以下代码就可以编译通过了:
1700440748
1700440749
public static void main(String[]args){
1700440750
1700440751
int i=100;
1700440752
1700440753
long l=(long)i;
1700440754
1700440755
f(l);
1700440756
1700440757
}
1700440758
1700440759
这就是int先加宽转变为long型,然后自动转换成Long型。规则说明白了,我们继续来看f(Integer.valueOf(i))是如何调用的,Integer.valueOf(i)返回的是一个Integer对象,这没错,但是Integer和int是可以互相转换的。没有f(Integer i)方法?没关系,编译器会尝试转换成int类型的实参调用,OK,这次成功了,与f(i)相同了,于是乎被加宽转变成long型—结果也很明显了。整个f(Integer.valueOf(i))的执行过程是这样的:
1700440760
1700440761
i通过valueOf方法包装成一个Integer对象。
1700440762
1700440763
由于没有f(Integer i)方法,编译器“聪明”地把Integer对象转换成int。
1700440764
1700440765
int自动拓宽为long,编译结束。
1700440766
1700440767
使用包装类型确实有方便的地方,但是也会引起一些不必要的困惑,比如我们这个例子,如果f()的两个重载方法使用的是基本类型,而且实参也是基本类型,就不会产生以上问题,而且程序的可读性更强。自动装箱(拆箱)虽然很方便,但引起的问题也非常严重—我们甚至都不知道执行的是哪个方法。
1700440768
1700440769
注意 重申,基本类型优先考虑。
1700440770
1700440771
1700440772
1700440773
[
上一页 ]
[ :1.700440724e+09 ]
[
下一页 ]