Overloading with widening, boxing and Varargs


Overloading with Boxing and Var-args

class AddBoxing {
  static void go(Integer x) { System.out.println("Integer"); }  
  public static void main(String [] args) {
     int i = 5;
     go(i); 
  }
}

Answer: Integer


class AddBoxing { 
  static void go(long x) { System.out.println("long"); }
  public static void main(String [] args) {
     int i = 5;
     go(i); 
  }
}

Answer: long

Now see...

class AddBoxing {
  static void go(Integer x) { System.out.println("Integer"); }
  static void go(long x) { System.out.println("long"); }
  public static void main(String [] args) {
     int i = 5;
     go(i); // which go() will be invoked?
  }
}

If it is given that both methods exist, which one will be used? In other words, does the compiler think that widening a primitive
parameter is more desirable than performing an autoboxing operation?
The answer is that the compiler will choose widening over boxing, so the output will be

long


The compiler will choose the older style before it chooses the newer style, keeping existing code more robust. So far we've seen that

1) Widening beats boxing
2) Widening beats var-args

class BoxOrVararg {
  static void go(Byte x, Byte y){ System.out.println("Byte, Byte"); }
  static void go(byte... x) { System.out.println("byte... "); }
  public static void main(String [] args) {
      byte b = 5;
      go(b,b);  // which go() will be invoked?
  }
}

As it turns out, the output is
Byte, Byte

Just remember that the var-args method is like a "looser" than the other method, in that it could handle invocations with any number of
byte parameters. A var-args method is more like a catch-all method, in terms of what invocations it can handle.
--------------------------------------------------------

Widening Reference Variables

class Car {static void drive() { } }

class BMW extends Car {
    public static void main(String[] args) {
        Car d = new Car();
        d.show(d);   // is this legal ?
    }
    void show(Car a) { }
}

Yes, no problem, The show() method needs an Car refernece, and BMW IS-A Car. You just remember, the show() method thinks it's getting an Car object, so it will only
ask it to do Car things, which of course anything that inherits from Car can do.
So, here the compiler widens the BMW reference to an Car, and the invocation succeeds.

The key point here is that reference widening depends on inheritance or we can say that the IS-A test. Because of this, it's not legal to widen
from one wrapper class to another, because the wrapper classes are peers to one another. For instance, it's NOT valid to say that Short IS-A Integer.

See...
class Vehical {
  public static void main(String [] args) {
     Vehical d = new Vehical();
     d.test(new Integer(5));  // can't widen an Integer to a Long
   }
   void test(Long x) { }
}

Here compilation will fails as it can not widen Integer to Long.

---------------------------------------------------------------
Overloading When Combining Widening and Boxing

class WidenAndBox {
  static void go(Long x) { System.out.println("Long"); }
  public static void main(String [] args) {
    byte b = 5;
    go(b); // must widen then box - illegal
  }
}

This is just too much for the compiler:
WidenAndBox.java:6: go(java.lang.Long) in WidenAndBox cannot be
applied to (byte)

class BoxAndWiden {
    static void go(Object o) {
        Byte b2 = (Byte) o; // ok - it's a Byte object
        System.out.println(b2);
     } 
     public static void main(String [] args) {
        byte b = 5;
        go(b); // can this byte turn into an Object ?
     }
 }

This compiles (!), and produces the output:
5

Here what happened:
1) First the byte b was boxed to Byte object
2) Now the Byte Object widened to Object because Byte is-A Object (Byte extends Object)
3) And then we have type cast Object o to Byte and then print

But in previous code we were passing byte b to method go(Long x), where is-A test failed. So compiler generates error.

--------------------------------------------------------

Overloading in Combination with Var-args'

class VarargDemo {
   static void wide_vararg1(long... x){ System.out.println("long..."); }
   static void box_vararg2(Integer... x){ System.out.println("Integer..."); }
   public static void main(String [] args) {
      int i = 5;
      wide_vararg1(i,i); // needs to widen and use var-args
      box_vararg2(i,i); // needs to box and use var-args
   }
}

This compiles and produces:
long...
Integer...

This seems easy.

Now see the rules for overloading methods using widening,boxing and varargs...

1) Primitive widening uses the "smallest" method argument possible.
2) Used individually, boxing and var-args are compatible with overloading.
3) You CANNOT widen from one wrapper type to another. (IS-A fails.)
4) You CANNOT widen and then box. (An int can't become a Long.)
5) You can box and then widen. (An int can become an Object, via Integer.)
6) You can combine var-args with either widening or boxing


Popular posts from this blog

Can not connect to git using ssh (Permissions 0644 for '/root/.ssh/id_rsa' are too open.

Upload file on Google cloud storage using Java servlet on google app engine

Session timeout interceptor in struts 2