“你好,阿米戈!几天前,我跟你说过关重载方法。你都懂了吗?”

“嗯。我记得。每个类的方法必须唯一。如果类不包含同名和同种参数类型的其他方法(参数的顺序很重要),那它的方法就是唯一的。”

“非常好。我看你也学过那课了。今天,我想稍微扩展一下这个主题的知识面。你认为每种情况下会调用哪种方法?”

代码
class Cat
{
 public static void print(int n)
 {
  System.out.println(n);
 }
 public static void print(short n)
 {
  System.out.println(n);
 }
 public static void print(Integer n)
 {
  System.out.println(n);
 }
 public static void print(String s)
 {
  System.out.println(s);
 }
public static void main(String[] args)
{
  Cat.print(1);
  Cat.print((byte)1);
  Cat.print("1");
  Cat.print(null);
 }
}

“难说。”

“在第一种情况下,1 是 int。我们有个完全匹配的方法带 int。此时会调用第一个 void print(int n)

在第二种情况下,我们没有带 byte 的方法。但有两个方法分别带 short 和 int。在类型拓宽规则基础上,byte 会首先拓宽为 short,然后拓宽为 int。因此,判定会调用 void print(short n)

在第三种情况下,我们有一个完全匹配的方法带 String。此时会调用 void print(String s)

第四种情况是模棱两可的。null 没有特定类型。编译程序将拒绝编译这个代码。在这种情况下,我们要编写 Cat.print((Integer)null) 来调用第三个方法,并且用 Cat.print((String)null) 来调用第四个方法。”

“非常有借鉴意义。谢谢你。”

“我想说的是,在确定正确的调用方法时,类型只能拓宽。它们不能缩小。不妨看这个例子:”

代码
class Cat
{
 public static void print(short n)
 {
  System.out.println(n);
 }
 public static void print(Integer n)
 {
  System.out.println(n);
 }

 public static void main(String[] args)
 {
  Cat.print((byte)1);
  Cat.print(1);
 }
}

在第一种情况下,byte 类型将拓宽为 short 类型,第一种方法将被调用:void print(short n)

在第二种情况下,将进行从 int 到 Integer 的隐式加宽拓宽转换,然后将调用第二种方法:void print(Integer n)

“没想到。”

“不,这是真正的惊喜:”

Java 语言代码 说明
 class Cat
{
 public static void print(Object o)
 {
  System.out.println(o);
 }
 public static void print(String s)
 {
  System.out.println(s);
 }

 public static void main(String[] args)
 {
  Cat.print(1);
  Cat.print(null);
 }
}
在第一种情况下,int 将扩展为 Integer。因为没有 Integer 的方法,所以最合适的方法(以及调用的方法)是 void print(Object o)

在第二种情况下,不会有任何编译错误,并且将调用 void print(Object o),这个不是特别明明显。

“阿米戈,我希望你理解在这种情况下,最好指定类型转换运算符(就像我们对“(byte)”所做的那样),以便确切地知道将调用哪种方法。”

“我从没想到重载方法会出现任何问题。但是后来你碰到了。谢谢你,里希。以后我会警惕这一点。”