Java进行方法调用时,可能会对参数的类型进行转换,以匹配到要调用的准确方法,在重载时要尤其注意这个问题。java语言规范中有相关的规定。
Method invocation conversion is applied to each argument value in a method or constructor invocation (§8.8.7.1, §15.9, §15.12): the type of the argument expression must be converted to the type of the corresponding parameter. Method invocation contexts allow the use of one of the following:
an identity conversion (§5.1.1)
a widening primitive conversion (§5.1.2)
a widening reference conversion (§5.1.5)
a boxing conversion (§5.1.7) optionally followed by widening reference conversion
an unboxing conversion (§5.1.8) optionally followed by a widening primitive conversion.
大体翻译一下: 方法调用转换适用于方法和构造方法的调用:参数表达式的类型必须转换为相应的参数的类型。(感觉这里argument是我们常提到的实际参数的意义,而parameter是方法中的形式参数的意思,英文容易区分,不过翻译过来怪怪的。)方法调用上下文允许使用以下类型转化:
1.同一转换。这里可以直接理解为就是同一类型的匹配。
2.拓宽基本类型转换。
3.拓宽引用类型转换。
4.装箱转换,后面可以随意地加上拓宽引用类型转换。
5.拆箱转换,后面可以随意地加上拓宽基本类型转换。
Method invocation conversions specifically do not include the implicit narrowing of integer constants which is part of assignment conversion (§5.2). The designers of the Java programming language felt that including these implicit narrowing conversions would add additional complexity to the overloaded method matching resolution process (§15.12.2).
再需要注意到就是方法调用约定不包括整数常量的处理,例如
public static voif test(short s){
}
test(12);是不能匹配上面定义的方法的。
例子:
使用test(s);首先选择的是test(short s)这个方法,使用的是 1.同一转换。
然后删除test(short s)方法,测试,这时会调用test(int i)这个方法,使用的是 2.拓宽基本类型转换。
删除test(int i)方法,测试,这时会调用test(float f)方法,使用的仍然是 2.拓宽基本类型转换。
删除test(float f)方法,测试,这时会调用test(Short s)方法,这时使用的是4.装箱转换。对short 变量s,装箱处理为Short,匹配test(Short s)方法。
删除test(Short s)方法,测试,这时会调用test(Number n)方法(特别注意,不是调用test(Integer i)方法)。这里使用的转换是4.装箱转换,后面可以随意地加上拓宽引用类型转换。首先short s被装箱得到Short类型变量,然后使用拓宽引用类型转换,得到Number类型。
最后我们删除test(Number n)方法,编译错误。也就是说short s不会先拓宽为int类型,再进行装箱处理。这点要注意。