benz
benz

Reputation: 4629

Why compiler gives ambigious method call error?

Here is a code snippet.

class BoxVar{

       static void call(Integer... i){
           System.out.println("hi"+i);
       } 
       static void call(int... i ){
           System.out.println("hello"+i);
       }
       public static void main(String... args){
                     call(10);
     }
}

The program compiles fine. When i run the program, it gives me

java: reference to call is ambiguous, both method call(java.lang.Integer...) in com.exams.BoxVar and method call(int...) in com.exams.BoxVar match

Can someone explain me the reason?

On top of it, i tried converting the first method to something like this.

 static void call(Long... i){
               System.out.println("hi"+i);
           } 

It ran fine. Can someone help me this problem? Thanks.

Upvotes: 1

Views: 90

Answers (2)

RealSkeptic
RealSkeptic

Reputation: 34648

You already got the answer as to why your program doesn't compile. I'll add the reason why it works with Long.

Naively, if you use something like:

long longVal = 10;

The compiler accepts it and does an automatic conversion from int to long.

But this doesn't work with the type Long, which expects actual long values:

Long longObj = 10; // Won't compile.

The same principle works when the compiler tries to resolve ambiguities. If you have two methods with the same name, but one accepts an int and one a Long, and you try to call it with the number 10, it recognizes that this number is integer, and that it's not a long value, and will therefore not be automatically boxed into a Long.

If you called it with the value 10L, it would see that the number is long, which is not compatible with int, but box-convertible to Long.

So there is no ambiguity trying to use call(10) in this case.

Upvotes: 2

Lews Therin
Lews Therin

Reputation: 10995

The compiler tells you exactly what is going on. Conceptually Integer and int types are the same. And thus, both method signatures are the same.

Assuming it compiled successfully, which method should the compiler call?

Types Long and Integer are not the same (in other words the compiler sees the integral types as two distinct types), that's why it compiled successfully:

int: By default, the int data type is a 32-bit signed two's complement integer, which has a minimum value of -231 and a maximum value of 231-1. In Java SE 8 and later, you can use the int data type to represent an unsigned 32-bit integer, which has a minimum value of 0 and a maximum value of 232-1. Use the Integer class to use int data type as an unsigned integer. See the section The Number Classes for more information. Static methods like compareUnsigned, divideUnsigned etc have been added to the Integer class to support the arithmetic operations for unsigned integers.

long: The long data type is a 64-bit two's complement integer. The signed long has a minimum value of -263 and a maximum value of 263-1. In Java SE 8 and later, you can use the long data type to represent an unsigned 64-bit long, which has a minimum value of 0 and a maximum value of 264-1. Use this data type when you need a range of values wider than those provided by int. The Long class also contains methods like compareUnsigned, divideUnsigned etc to support arithmetic operations for unsigned long.

See Integral Types as reference.

Upvotes: 5

Related Questions