Java重载方法匹配优先级

      在我们学习Java的时候关于重载有个小的知识点叫方法重载匹配优先级。虽然javac编译器能确定方法的重载版本,但是在很多情况下重载的版本并不是唯一的,往往只能确定一个相对合适的版本。请看以下代码你觉得输出的内容是什么呢?(可以先不要翻到代码结束后的答案尝试猜测)

package cn.laoniu;

import java.io.Serializable;

public class Reload {

	public void sayType(Character arg) {
		System.out.println("Character");
	}

	public void sayType(long arg) {
		System.out.println("long");
	}

	public void sayType(char arg) {
		System.out.println("char");
	}

	public void sayType(char... arg) {
		System.out.println("char...");
	}

	public void sayType(Serializable arg) {
		System.out.println("Serializable");
	}

	public void sayType(int arg) {
		System.out.println("int");
	}

	public void sayType(Object arg) {
		System.out.println("Object");
	}

	public static void main(String[] args) {
		new Reload().sayType('a');
	}

}

上面代码的运行后输出结果为:

char

      这很好理解,'a'是一个char类型的数据,自然会寻找参数类型为char的重载方法,如果注释掉sayType(char arg)方法,那么输出结果会变为:

int

     这时发生了一次自动类型转换,'a'除了可以代表一个字符串,还可以代表数字97(字符'a'的Unicode数值为十进制数字97),因此参数类型为int的重载也是合适的。我们继续注释掉sayType(int arg)方法,那么输出的结果会变为:

long

    这时发生了两次类型转换,'a'转型为整数97之后,进一步转型为长整数97L,匹配参数类型为long的重载。虽然上面代码中没有加入其他类型如float、double等的重载,在实际上自动转型还能继续发生多次,按照char>int>long>float>double的顺序进行匹配,但是不会匹配到byte和short类型的重载,因为char到byte和short的转型是不安全的。我们继续注释掉sayType(long arg)方法,那么输出的结果变为:

Character

    这时发生了一次自动装箱,'a'被包装为它的封装类型java.lang.Character,所以匹配到了参数类型为Character的重载,继续注释掉sayType(Character arg)方法,那么输出的结果会变为:

Serializable

    这个输出可能会让人感到疑惑,一个字符或数字与序列化有什么关系呢?出现Serializable是因为java.lang.Serializable是java.lang.Character类实现的一个接口,当自动装箱之后发现还是找不到装箱类,但是找到了装箱类所实现的接口类型,所以紧接着又发生了一次自动转型。char可以转型为int,但是Character是绝对不会转型为Integer的,它只能安全地转型为它实现的借口或者父类。Character还实现了另外一个接口java.lang.Compara<Character>,如果同时出现两个参数分别是Serializable和Compara<Character>的重载方法,那它们在此时的优先级是一样的。编译器无法确定要自动转型为哪种类型,会提示“类型模糊”(Type Ambiguous),并拒绝编译。让我们继续注释掉sayType(Serializable arg)方法,输出结果会变为:

Object

    这时是char装箱后转型为父类了,如果有多个父类,那么继承关系从下往上搜索,越往上层优先级越低。即便方法调用传入参数值null时,这个规则仍然适用。继续把sayType(Object arg)方法注释掉,结果会变为:

char...

    此时就剩下这一个方法了,可见变长参数的重载优先级是最低的。

补充

   上面例子演示了Java重载方法优先匹配级别,这也属于java编译期间选择静态分配目标。这个例子是很极端的例子,除了作为面试题来为难应聘者之外在实际工作中几乎不存在任何价值

猜你喜欢

转载自blog.csdn.net/qq_41389354/article/details/115675923