The blog of Jafar Aliyev

Archive

Creation date:

Overloading

Overloading is one of the main feature of Java language. When class has overloaded methods, compiler has to determine which method will be run. Overloading in conjuction with autoboxing and var-args gets hard to understand.

class A {
   static void go(long i){
      System.out.println("long");
   }
   static void go(Integer i){
      System.out.println("Integer");
   }
   static void go(int... i){
      System.out.println("int...");
   }
   static void go(Integer i, Integer k){
      System.out.println("Integer, Integer");
   }
   static void go(Object i){
      System.out.println("Object");
   }
   public static void main(String[] args) {
      int k=900;
      short s = 100;
      go(k);
      go(k,k);
      go(k,k,k);
      go(new Short(s));
      go(new Short(s), new Short(s));
   }
}

This example is quite tricky because I joined several exceptional cases in one class. First look at result and try to understand, what's going on.

long
Integer, Integer
int...
Object
int...

Now let's explain every line in output and validate the behaviour of compiler.

First we call go() with a primitive int argument. As you see we don't have go() method with int parameter. It may seem, that the method with Integer parameter will be applied. But it's not the case. Java first looks for wider primitive type, then for wrapper class. If we delete the go(long i) method, go(Integer i) will be applied instead. Explanation is obvious. Because widening capability existed before wrapper classes, preexisting codes should function the same way as before Java 5, designers made decision to choose widening over boxing. Widening beats boxing.

On second line we get Integer, Integer as the result of call go(k,k). Here we see, that both int arguments wrapped to Integer and go(Integer, Integer) method is called, although we have go(int...) method. It means boxing beats var-args. The reason is the same as in first case, compiler chooses older style to make decision. Widening also beats var-args. If we add go(long i, long j) method and call go(k,k) it'll call go(long i, long j) instead of go(int...).

In third case arguments match the parameter of go(int...) method without any boxing.

On fourth call go(new Short(s)); compiler widens Short to Object, because it can't widen it to Integer. Remember that all numeric wrappers are extend Numeric, but not each other.

On last call both Short objects are unboxed to short, then widened to int and go(int...) is called.

Author: Jafar N.Aliyev (Jsoft)

Read also

Use instanceof carefully
Usage of 'instanceof' method in some situations will give you a compilation error

Wrapper objects

Static and instance initilization blocks

Java access and nonaccess modifiers
Look at this cheat sheet for Java access and nonaccess modifiers

Implicit typecasting

Protected details

Interface methods are always public

Static methods can not be overriden
Here I explain, why static methods can not be overriden

Implicit typecasting

Java Tips

Variable hiding

Postfix operators

Tricky Polymorphism

Pattern Matching

Default values

String equality

© Copyright

All articles in this site are written by Jafar N.Aliyev. Reproducing of any article must be followed by the author name and link to the site of origin(this site). This site also keeps the same rules relative to the articles of other authors.