本文共 1588 字,大约阅读时间需要 5 分钟。
例如,一个类中有诸多的重载方法,那么参数char arg = 'a';
在调用下面的方法时,会发生什么呢?
public static void sayHello(Object arg) { System.out.println("Object"); }public static void sayHello(int arg) { System.out.println("int"); }public static void sayHello(long arg) { System.out.println("long"); }public static void sayHello(Character arg) { System.out.println("Character"); }public static void sayHello(char arg) { System.out.println("char"); }public static void sayHello(char... arg) { System.out.println("char..."); }public static void sayHello(Serializable arg) { System.out.println("Serializable"); }
执行第 n 次数 | JVM 执行方法的输出结果 | 方法执行后的操作 |
---|---|---|
1 | char | 注释参数为 char 的方法 |
2 | int | 注释参数为 int 的方法 |
3 | long | 注释参数为 long 的方法 |
4 | Character | 注释参数为 Character 的方法 |
5 | Serializable | 注释参数为 Serializable 的方法 |
6 | Object | 注释参数为 Object 的方法 |
7 | char… | 注释参数为 char… 的方法 |
为什么?
我们都知道向上转型,例如:class Man extends Human
,此时声明Human man = new Man();
,等号左边的Human
称为变量man
的静态类型,等号右边的Man
称为变量man
的实际类型。举这个例子是为了明确这两个名词,然后再来解释方法重载时,JVM
如何确定调用哪个方法。 方法重载时依赖静态类型来定位方法执行版本的分派,即静态分派。静态分派发生在编译阶段,因此确定静态分派的动作实际上不是由虚拟机来执行的。另外,编译器虽然能确定方法的重载版本,但在很多情况下这个重载版本并不是“唯一的”,往往只能确定一个“更加合适的”版本。 'a'
是一个char
类型的数据,那么参数为char
的方法是最适合的char
自动转型为int、long、float、double
类型的数据(char
转byte
和short
会损失精度),精度由小到大优先匹配,基本数据类型优先考虑。char
进行一次自动装箱,被封装为包装类型Character
char
装箱后转型为父类,因为Character
实现Serializable
和Comparable
接口,因此可以匹配参数为这两个接口的方法,但如果同时出现两个参数分别为Serializable
和Comparable
的重载方法,那么编译器会拒绝编译char
的顶级父类是Object
。如果有多个父类,那么将在继承关系中从下往上开始搜索,越往上优先级越低。即使传入的参数值为null
时,这个规则仍然使用。这里要特别注意null
,详情请看注意:char[]
是数组类型,因此不能匹配char arg = 'a';
参数。
结论:优先匹配顺序:类型匹配>基本数据类型>包装类型>父类(不包含Object,且同时存在多个父类匹配时,JVM首先不会答应)>Object>变长
转载地址:http://cvcsn.baihongyu.com/