Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Theoretical inquiry about overloading and type promotion in java

If there are two methods like add(int,long) and add(long,int), such call add(10,10) would be considered as ambiguity.

But what if we have such example, why is it still considered as ambiguity??

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);
}

I want to know how the compiler decided that it is ambiguity? while (in my mind) it shouldn't because add(short, short) needs two steps of type promotion, and add(byte, long) needs three steps of type promotion .. or do I have a misconception??

like image 686
Abd-Elrahman Adel Avatar asked Jan 10 '18 01:01

Abd-Elrahman Adel


2 Answers

See 8.4.9. Overloading - from the Java Language Specification and the "overloading resolution procedure" - and, specifically 15.12.2.5. Choosing the Most Specific Method.

If more than one member method is both accessible and applicable to a method invocation, it is necessary to choose one to provide the descriptor for the run-time method dispatch. The Java programming language uses the rule that the most specific method is chosen.

..

One applicable method m1 is more specific than another applicable method m2, for an invocation with argument expressions e1, ..., ek, if any of the following are true:

  • [..]

  • m2 is not generic, and m1 and m2 are applicable by strict or loose invocation, and where m1 has formal parameter types S1, ..., Sn and m2 has formal parameter types T1, ..., Tn, the type Si is more specific than Ti for argument ei for all i (1 ≤ i ≤ n, n = k).

  • [..]

..

It is possible that no method is the most specific, because there are two or more methods that are maximally specific .. [there are more rules wrt concrete/abstract..]

Otherwise, the method invocation is ambiguous, and a compile-time error occurs.

The Java compiler just follows these rules; a different language will follow different rules, and a human might invent their own non-Java rules when deciding which overload to pick..


For a method to be selected as more specific, it must be more specific for all parameters. Thus the example case results in a ambiguous invocation when invoked as add(byte,byte) because:

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

However, if add(byte num1, long num2) was changed to add(byte num1, short num2) it would compile because:

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

The relationship between primitives is in 4.10.1. Subtyping among Primitive Types: long > int > short > byte:

like image 91
user2864740 Avatar answered Sep 28 '22 22:09

user2864740


Matching the actual argument types to the method parameter lists requires type coercion in both cases, so neither is a "perfect" match and therefore ambiguous. If you add

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

it's a perfect match and there is no ambiguity.

like image 34
Jim Garrison Avatar answered Sep 29 '22 00:09

Jim Garrison