java: reference to .. is ambiguous, both method method1 and method2 in ... match [duplicate]

StackOverflow https://stackoverflow.com/questions/22234497

Pergunta

I faced with same code:

    public class Devk{
        public static void tMeth(Integer... i){
          System.out.print("A");
        }
        public static void tMeth(int... i){
          System.out.print("B");
        }
        public static void main(String args[]){
          tMeth(Integer.valueOf("7"));//compile error
          tMeth(new int[2]); //returns B
          tMeth(new Integer[2]); //returns A
        }

  }

after invokation I see

java: reference to tMeth is ambiguous, both method tMeth(java.lang.Integer...) in GenericsTest.Test1 and method tMeth(int...) in GenericsTest.Test1 match

method Integer.valueOf("7") returns Integer wrapper. I expect to see A in console.

Who can explain this behaviour and provide general rule for this ?

P.S.

public static void tMeth(Integer i){
    System.out.print("A");
}
public static void tMeth(int i){
    System.out.print("B");
}
public static void main(String args[]){
    tMeth(1); //returns B
    tMeth(new Integer(1)); //returns A
}
Foi útil?

Solução

When compiling a method call, the compiler searches for a matching method in this order:

  1. Try to find a method without autoboxing/unboxing or varargs.
  2. If no method is found, see if a method matches using autoboxing/unboxing.
  3. If still no method is found, see if a method matches using both varargs and autoboxing/unboxing.

In your case, you are in step (3) here. Since unboxing is allowed, both methods are applicable.

The compiler then tries to find the one that is most specific. One method is more specific than another if its parameter types are all equally or more specific (for example, String is more specific than Object, and int is more specific than long).

But between int and Integer, neither is more specific; the compiler relies on testing (1) before (2) above to get the correct method in the case of, say, foo(int) and foo(Integer).

So, there are two applicable methods and neither is more specific, hence the ambiguity error.

JLS reference

Outras dicas

This behavior is caused by Java's auto-boxing respectively Java's auto-unboxing.

Java will automatically convert primitive types to its corresponding wrapper classes and wrapper classes to its corresponding primitive types. That makes it possible to pass an "int" to a method which requires an "Integer" or an "Integer" to a method which requires an "int". Java will automatically convert the types.

In your specific case this causes the ambiguity, since there are two potential methods available for the call.

You can read more about it here: http://docs.oracle.com/javase/tutorial/java/data/autoboxing.html

This is because of a feature called 'Autoboxing' in java where a given primitive value will automatically be boxed into it's wrapper class. The primitive value here is int and the wrapper class is Integer. Since 7 matched both primitive value 7 and Integer value 7, both methods collide.

Since the compiler will pass a primitive value to arguments matching primitive and wrapper type (and vice versa for wrapper type), you are not really overloading methods here as much as duplicating them.

Integer (and Double, Byte, Float, Long, etc.) are the wrapper classes of the primitive data types.

You can't have one method using int and another using Integer since Java 5 because of autoboxing, which will convert any int variable to its Integer counterpart (and any Integer to int, raising a NullPointerException if the object is null).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top