Monday 8 December 2014

Method Overloading resolution in Java

Background

Instead of giving an overview of what this post entails let me give you a quick problem to solve. Lets say you have few methods

public static void execute( int data) {System.out.println("int")}
public static  void execute( short data) {System.out.println("short")}
public static  void execute( Object data) {System.out.println("object")}
public static  void execute( String data) {System.out.println("string")}


and I call following methods - 

public static void main(String[] args) {
    byte byt = 3;
    execute(byt); // 1st call
    execute(10); // 2nd call
    Integer i = 6;
    execute(6); // 3rd call
    execute("Test"); // 4th call
}

What would be the output ?
It would be - 

short
int
object
string

Surprised? Wondering ?

Will solve the mystery in a minute :). Lets get our basics clear first and then there would be no need for me to go ahead and explain the outputs.

Few points to note about the question -
  1. The methods you see have same name, return type but different types of arguments. This is called method overloading. For more details refer Overriding Methods in Java - How it works?
  2. Next we are calling methods some of which that do not exactly match the ones which are defined. Like calling execute() with byte 3. There is no method which takes byte as argument. But there is short, int and even Object argument methods that are compatible. Note the word "compatible" but only one is chosen from it - and we saw it was short in this case. Java as all programming languages has rules which dictates these things which is exactly what we will see in some time.

Rules for method overloading resolution

  1.  Java Compiler always tries to choose the most specific method available with least number of modifications to the arguments.
  2. Next point is about Boxing / Unboxing. Java developers wanted the old code to work exactly the same a sit used to work before boxing / unboxing.
  3. With points 1 and 2 in mind the order in which preference is given is -

    Widening (size wise)[Minimum first] > Boxing/Unboxing > variable arguments.

 Primitive types sizes in Java

  • byte: The byte data type is an 8-bit signed two's complement integer.
  • short: The short data type is a 16-bit signed two's complement integer.
  • int: By default, the int data type is a 32-bit signed two's complement integer.
  • long: The long data type is a 64-bit two's complement integer. 
  • float: The float data type is a single-precision 32-bit IEEE 754 floating point.
  • double: The double data type is a double-precision 64-bit IEEE 754 floating point.
  • boolean: The boolean data type has only two possible values: true and false.
  • char: The char data type is a single 16-bit Unicode character.

Primitive types default values in Java



Now give the question in backgrounds section another try.

With above rules in mind lets try to solve the question posted at the top of this post.

First call was

byte byt = 3;
execute(byt); // 1st call

As per above rule most preferred was would be widening. There are two options here. Widen byte (8bit) to a short (16 bit) or an int (32 bit). Widening with lowest size is preferred (which is short in this case) and hence we got short printed.

Next is

execute(10); // 2nd call

and is a direct call as we have execute method with int parameter. So int is printed.

Next we have

Integer i = 6;
execute(6); // 3rd call

Since we do not have a method with Integer as argument we will go for next best case and that is polymorphic superclass. Object is superclass of all objects implicitly. So we get object printed.

Lastly we have

execute("Test"); // 4th call

Again we have execute method with String which is chosen here. Again straight forward.

Note : Widening is preferred over boxing/unboxing which is preferred over variable arguments. By variable arguments I mean something like

public void execute (int ...x)

Hope this clarifies all doubts regarding our original question.

Note : Java Compilation will fail if there are no matches or ambiguous matches for a function call.

Example of no matches : 

Methods available are

public static  void execute( short data) {System.out.println("short")}
public static  void execute( byte data) {System.out.println("byte")}

and you call

execute (10) // execute (int)

Example of ambiguous matches : 


Methods available are

public static  void execute( int data1, long data2) {System.out.println("int-long")}
public static  void execute( long data1, int data2) {System.out.println("long-int")}

and you call

execute (1,2) // execute (int,int)

Related Links


t> UA-39527780-1 back to top