Java: passing an argument with a different type to a function

Initially primitive widening will happen for a primitive type. For example you want to call

 int input = 5; //int variable;
 apply(input); //calling method with int value. 

But your class not contains a method which argument accept int so compiler will go for primitive widening. It will check any apply method with java long argument present or not. If present that method will be invoked. If not it will check for apply with a float argument is present and then it will be selected. If that also not find it will look for apply with a double argument.

public void apply(long input) {
    System.out.println("long");   // first pick by the compiler.
}
public void apply(float input) {
    System.out.println("float"); // if above method not found this will be selected.
}
public void apply(double input) {
    System.out.println("double"); // above two methods not present this will be selected.
}

Next, If all above three methods not found then compiler will look for Autoboxing this and try to convert that to its corresponding wrapper. for int its java.lang.Integer.So it will check for apply with Integer argument. If this found compiler will execute this method.

public void apply(Integer input) {
    System.out.println("Integer");
}

Finally if none of the above present, compiler looks for any method with name apply which accepts int... or Integer... and the method is invoked.

public void apply(int... input) {
    System.out.println("int...");
}

If your class contains only below two methods

public void apply(long input) {
    System.out.println("long");
}
public void apply(float input) {
    System.out.println("float");
}

and you want to pass a double value in to this method, it wont compile.

double input = 5d;
apply(input); 
// The method apply(long) in the type YourClass 
//is not applicable for the arguments (double

If you want to make that work you have to type cast that to something which can be accepted by your methods.

apply((int) input);

Then compiler will try to find a match by exact type or primitive widening or autoboxing or array matching way.


See JLS - Section # 5.3 for details on Method Invocation Conversion.

Method invocation contexts allow the use of one of the following:

- an identity conversion (§5.1.1)
- a widening primitive conversion (§5.1.2)
- a widening reference conversion (§5.1.5)
- a boxing conversion (§5.1.7) optionally followed by widening reference conversion
- an unboxing conversion (§5.1.8) optionally followed by a widening primitive conversion.

So, your first invocation(int to double) will work fine according to rule # 2.

But the second invocation(double to int) will give Compiler Error, according to the statement quoted further in the same section: -

If the type of the expression cannot be converted to the type of the parameter by a conversion permitted in a method invocation context, then a compile-time error occurs.


Because you can set a double to an integer, then integer as argument is ok to function with double as parameter. Other way round fails. In that case you need to cast the double to an int. Same applies to normal assignents eg..

  int i = 6;
  double d = 0;
  d = i;  /* ok
  i = d ; /* not ok

You can get sometimes get around this by making your function take a parameter of Number. This is an Object which both Integer and Double inherit from, so up to the point where a Double number and an Integer number behave the same, this will work.

Note that there is a difference between the primitives integer and double and the Objects Integer and Double. Java uses autoboxing to automatically convert between these types in function calls, etc.