关于java中重载和类型提升的理论探讨

时间:2018-01-10 01:14:26

标签: java overloading type-promotion

如果有add(int,long)add(long,int)两种方法,则此类调用add(10,10)将被视为含糊不清。

但是,如果我们有这样的例子,为什么它仍然被认为是歧义?

static void add(short num1, short num2) {
    System.out.println("add(short, short)");
}

static void add(byte num1, long num2) {
    System.out.println("add(byte, long)");
}

public static void main(String[] args) {
    byte num1 = 10;
    byte num2 = 10;

    add(num1, num2);
}

我想知道编译器如何确定它是模棱两可的?虽然(在我看来)它不应该因为add(short, short)需要两个类型提升步骤,而add(byte, long)需要三个类型提升步骤..或者我是否有误解?

2 个答案:

答案 0 :(得分:3)

请参阅8.4.9. Overloading - from the Java Language Specification"overloading resolution procedure" - 特别是 15.12.2.5。选择最具体的方法

  

如果多个成员方法都可访问并适用于方法调用,则必须选择一个为运行时方法调度提供描述符。 Java编程语言使用选择最具体方法的规则。

     

...

     

一个适用的方法m1 比另一个适用的方法m2更具体,用于参数表达式e1,...,ek,的调用,如果以下任何一个是真:

     
      
  • [..]

  •   
  • m2不是通用的,m1和m2适用于严格或松散的调用,其中m1具有形式参数类型S1,...,Sn和m2具有形式参数类型T1,...,Tn ,对于所有i(1≤i≤n,n = k),对于参数ei,Si的类型比Ti更具特异性。

  •   
  • [..]

  •   
     

...

     

有可能没有方法是最具体的,因为有两个或更多的方法是最具体的.. [有更多的规则具体/抽象..]

     

否则,方法调用不明确,并发生编译时错误。

Java编译器遵循这些规则;不同的语言将遵循不同的规则,并且人们在决定选择哪个重载时可能会发明自己的非Java规则。

对于选择更具体的方法,所有参数必须更具体。因此,示例案例在调用add(byte,byte)时会导致模糊调用,因为:

  • add(short num1 /* less specific */, short num2 /* MORE specific */)
  • add(byte num1 /* MORE specific */, long num2 /* less specific */)

但是,如果add(byte num1, long num2)更改为add(byte num1, short num2),则会编译,因为:

  • add(short num1 /* less specific */, short num2 /* as specific */)
  • add(byte num1 /* MORE specific */, short num2 /* as specific */)

基元之间的关系在4.10.1. Subtyping among Primitive Types中:long> int>简短>字节:

答案 1 :(得分:1)

将实际参数类型与方法参数列表匹配在两种情况下都需要类型强制,因此两者都不是“完美”匹配,因此不明确。如果你添加

static void add(byte num1, byte num2) {
    System.out.println("add(byte, byte)");
}

这是一个完美的匹配,并没有歧义。