Thursday, April 12, 2012

Autoboxing,Autounboxing and Overloading in Java

Introduction

Auto-boxing and AutoUnboxing is the new feature added in Java 5 where java compiler automatically converts the primitive(basic) data types into corresponding object wrapper classes and vice versa.

Autoboxing example:-
Prior to Java 5,if we have to add int/long/double/.... primitives into any collection classes,we have to explicitly convert them into corresponding Number wrapper classes and add them into collection.However with the advent of Java 5,we need not have to explicitly do the same.It happens automatically as compiler generates the code which converts primitive to wrapper classes and vice versa.

Code prior to Java 5
int data1=29;
int data2=30;
long data3=56;
float data4=12.3f;

List dataList=new ArrayList();
dataList.add(new Integer(data1));
dataList.add(new Long(data2));
dataList.add(new Float(data3));

Code as per Java 5
int data1=29;
int data2=30;
long data3=56;
float data4=12.3f;

List dataList=new ArrayList();
dataList.add(data1);
dataList.add(data2);
dataList.add(data3);

So in Java 5,we need not have to convert the primitive data types into Number wrapper classes.Its taken by the compiler which handle it seamlessly

Autounboxing example:-
Prior to Java 5 if we have to do any increment/decrement of the wrapper object.We have to get the primitive value from the wrapper number object ,increment/decrement the same and push it back to wrapper object.

Code prior to Java5
Integer intData=new Integer(10);
int primitiveVal=intData.intValue();
primitiveVal++;
intData=new Integer(primitiveVal);

Long longData=new Long(20);
long primVal=longData.longValue();
primVal++;
longData=new Long(primVal);

Code as per Java5
Integer intData=new Integer(10);
intData++;

Long longData=new Long(20);
longData++;

So in Java5,we need not have to convert wrapper objects into primitives for increment/decrement operations.


Overloading and auto boxing/unboxing

So how does auto boxing/unboxing affects overloading.It follows following principles.These are:-
i)First it tries to find the method matching the exact data type.
ii)In case of wrapper classes,if it does not find any method as per step -1.It tries to find the method matching the corresponding primitive data type.
iii)If it does not find any method corresponding to step-2.Then it tries to find the method matching the widen primitive data type.

i.e
If in a class we have overloaded method display taking byte/long as parameters and we invoke display method with Integer as parameter.It will invoke display method having long as parameter

Inorder to understand better lets go through some examples.

Example-1:-
In this example we have overloaded methods taking Integer object and primitive int.So when we invoke this for int or Integer object ,it invokes the corresponding method



package com.kunaal.overloading;

/**
 * 
 * @author KunaalATrehan
 *
 */
public class BasicOverLoadingTest {

 /**
  * Overloaded display method taking primitive integer
  * @param i
  */
 private void display(int i){
  System.out.println("Primitive method invoked,data is -"+ i);
 }
 
 /**
  * Overloaded display method taking integer number wrapper class
  * @param i
  */
 private void display(Integer i){
  System.out.println("Number wrapper method invoked,data is-"+ i);
 }
 
 /**
  * @param args
  */
 public static void main(String[] args) {
  BasicOverLoadingTest dataObj=new BasicOverLoadingTest();
  dataObj.display(10);
  dataObj.display(new Integer(789));
 }

}

Output

Primitive method invoked,data is -10
Number wrapper method invoked,data is-789

Example 2:-


In this example we will test the rule -2.We have overloaded methods taking int and long primitive data type.Then we invoke the overloaded method for Long wrapper class.So when we invoke the overloaded method for Long data type,invokes the overloaded method which has primitive long as parameter.


package com.kunaal.overloading;

/**
 * @author KunaalATrehan
 *
 */
public class ShortenOverloadingTest {
 
 /**
  * Overloaded display method taking primitive int as parameter
  * 
  * @param i
  */
 private void display(int i){
  System.out.println("Display invoked for primitive int,data is :-"+ i);
 }
 
 /**
  * Overloaded display method taking primitive long as parameter
  * @param i
  */
 private void display(long i){
  System.out.println("Display invoked for primitive long,data is :-"+ i);
 }

 /**
  * @param args
  */
 public static void main(String[] args) {
  ShortenOverloadingTest dataObj=new ShortenOverloadingTest();
  dataObj.display(10);
  dataObj.display(new Long(100));
 }

}


Output


Display invoked for primitive int,data is :-10
Display invoked for primitive long,data is :-100

Example 3:-

In this example we will test the rule-3.We have overloaded methods taking primitive byte,int,float and Integer wrapper.When we invoke the method for Long wrapper parameter,it invokes the method having float as parameter.Since there is no matching method for Long wrapper class.It searches for method having long primitive data type.Since there is no such method available,it finds a method which can take parameter bigger than long primitive data type which in this case is float.So it invokes the same for Long wrapper object.


package com.kunaal.overloading;

/**
 * @author KunaalATrehan
 *
 */
public class OverloadingTest {

 /**
  * Overloaded method for primitive byte
  * @param i
  */
 private void display(byte i){
  System.out.println("Display invoked for primitive byte,data is -"+ i);
 }

 /**
  * Overloaded method for primitive int
  * @param i
  */
 private void display(int i){
  System.out.println("Display invoked for primitive int,data is -"+ i);
 }
 
 /**
  * Overloaded method for primitive float
  * @param i
  */
 private void display(float i){
  System.out.println("Display invoked for primitive float,data is-"+ i);
 }
 
 /**
  * Overloaded method for Integer wrapper object
  * @param i
  */
 private void display(Integer i){
  System.out.println("Display invoked for Integer wrapper,data is-"+ i);
 }
 
 /**
  * @param args
  */
 public static void main(String[] args) {
  OverloadingTest dataObj=new OverloadingTest();
  byte data=32;
  dataObj.display(data);
  dataObj.display(30);
  dataObj.display(new Long(909090));
  dataObj.display(null);
 }

}

Output


Display invoked for primitive byte,data is -32
Display invoked for primitive int,data is -30
Display invoked for primitive float,data is-909090.0
Display invoked for Integer wrapper,data is-null

Saturday, March 31, 2012

Enums demystified

Why enums came into picture?

Before enums came into picture we all were using constants for different values.
There would be a constant file in which we define values like this

public static final int LOW=1;
public static final int MEDIUM=2;
public static final int HIGH=3;

Above approach works,but there are following issues.These are:-
i)Programmer is not bounded to use the constants.Programmer can put any int value and code will work fine.
ii)LOW/MEDIUM/HIGH are just variable names. So when we print LOW/MEDIUM/HIGH it prints 1/2/3 which does not convey any meaning.

So java introduced enums.Enum is like a class or interface which is used to define a set of constants.Enum constants can't be changed once created and we are free to add behavior to it by adding abstract methods and interfaces.It provides type safety and can be used inside a switch statement.Moreover they are initialized when enum class is loaded.



Plain enums

Plain enum are constants without any parametrized value.In the current example-GenderEnum we are having two constants M,F for male and female gender respectively.

package com.kunaal.enumDetails;

/**
 * @author KunaalATrehan
 *
 */
public enum GenderEnum {
 M,F;
}


Parametrized enums



Plain enum do provide type safety.However to provide more meaningful implementation we have to use overloaded constructor of the enum.

Lets take the example of Income group enum.Here by using parametrized enum we are able to convey the meaning of enum constant more effectively.

package com.kunaal.enumDetails;

/**
 * @author KunaalATrehan
 *
 */
public enum IncomeGroupEnum {
 BPL("Below Poverty Line"),
 LIG("Lower Income Group"),
 MIG("Middle Income Group"),
 HIG("High Income Group");
 
 //Variable for data val
 private String dataVal;

 /**
  * @return the dataVal
  */
 public String getDataVal() {
  return dataVal;
 }

 /**
  * Parameterized constructor
  * @param dataVal
  */
 private IncomeGroupEnum(String dataVal) {
  this.dataVal = dataVal;
 }

}








Are enums similar to normal java classes?

Enums are exactly like java classes.Enums can implement an interface and can have abstract methods.In order to understand it better,lets take an example.

Here we are creating an enum for educational qualifications.This enum has an abstract method called print(). This abstract print() method is overridden by each enum value.

package com.kunaal.enumDetails;

/**
 * @author KunaalATrehan
 *
 */
public enum EducationDtlEnum {
  PG("Post Graduate") {
   @Override
   public void print() {
    System.out.println("Person may have done MBA,MCA,MS or similar things");
   }
  },
  UG("Under Graduate") {
   @Override
   public void print() {
    System.out.println("Person may have done Diploma. ");
   }
  },
  GRAD("Graduate") {
   @Override
   public void print() {
    System.out.println("Person may have done BE,BTech,BSC,BBA or similar things");
   }
  },
  HS("High School") {
   @Override
   public void print() {
    System.out.println("Person has finished the high school");
   }
  },
  PHD("Doctorate") {
   @Override
   public void print() {
    System.out.println("Person may have doen PHD,MD or similar things.");
   }
  };
  
  //Variable for dataval
  private String dataVal;
  
  /**
   * Parameterized constructor
   * @param value
   */
  private EducationDtlEnum(String value){
   this.dataVal=value;
  }

  /**
   * @return the dataVal
   */
  public String getDataVal() {
   return dataVal;
  }
  
  //Abstract print method
  public abstract void print();
}


Enum example using plain,parametrized and enums with abstract method

Person class containing following variables
-String variable for name
-Plain enum 'GenderEnum' for capturing person's gender
-Parametrized enum 'IncomeGroupEnum' for capturing person's income group
-Parametrized enum 'EducationDtlEnum' with abstract method print()

package com.kunaal.enumDetails;

/**
 * @author KunaalATrehan
 *
 */
public class Person {
 
 //Enum for education details
 private EducationDtlEnum educationInfo;
 
 //Enum for income group
 private IncomeGroupEnum incomeGroup;
 
 //Variable for name
 private String name;
 
 //Variable for gender
 private GenderEnum genderEnum;

 /**
  * @return the genderEnum
  */
 public GenderEnum getGenderEnum() {
  return genderEnum;
 }

 /**
  * @param genderEnum the genderEnum to set
  */
 public void setGenderEnum(GenderEnum genderEnum) {
  this.genderEnum = genderEnum;
 }

 /**
  * @return the educationInfo
  */
 public EducationDtlEnum getEducationInfo() {
  return educationInfo;
 }

 /**
  * @param educationInfo the educationInfo to set
  */
 public void setEducationInfo(EducationDtlEnum educationInfo) {
  this.educationInfo = educationInfo;
 }

 /**
  * @return the incomeGroup
  */
 public IncomeGroupEnum getIncomeGroup() {
  return incomeGroup;
 }

 /**
  * @param incomeGroup the incomeGroup to set
  */
 public void setIncomeGroup(IncomeGroupEnum incomeGroup) {
  this.incomeGroup = incomeGroup;
 }

 /**
  * @return the name
  */
 public String getName() {
  return name;
 }

 /**
  * @param name the name to set
  */
 public void setName(String name) {
  this.name = name;
 }
 
 /**
  * Overridden toString() method
  */
 @Override
 public String toString() {
  return "Person [educationInfo=" + educationInfo + ", genderEnum="
    + genderEnum + ", incomeGroup=" + incomeGroup + ", name="
    + name + "]";
 }
}

Enum example making different concrete implementation of Person class.
This example contains different methods to test different functionalities provided by enum.
i.e
-printValues() prints enumeration value.
-refCheck(..) checks for == implementation.
-abstractEnumMthdImpl(...) invokes overridden abstract method in different enums.
-defaultToString(..) invokes toString() method of the enum
-equalityChk(..) checks for equals implementation.

package com.kunaal.enumDetails;

/**
 * @author KunaalATrehan
 *
 */
public class EnumExample {

 /**
  * @param args
  */
 public static void main(String[] args) {
  Person person=new Person();
  person.setName("Mr. A");
  person.setEducationInfo(EducationDtlEnum.PHD);
  person.setIncomeGroup(IncomeGroupEnum.HIG);
  person.setGenderEnum(GenderEnum.M);
  
  Person person2=new Person();
  person2.setName("Mrs. B");
  person2.setEducationInfo(EducationDtlEnum.PHD);
  person2.setIncomeGroup(IncomeGroupEnum.HIG);
  person2.setGenderEnum(GenderEnum.F);
  
  Person person3=new Person();
  person3.setName("Mr. C");
  person3.setEducationInfo(EducationDtlEnum.PG);
  person3.setIncomeGroup(IncomeGroupEnum.MIG);
  person3.setGenderEnum(GenderEnum.M);
  
  //print enum data 
  printValues();
  
  //chk for references
  refCheck(person, person2, person3);
  
  //testing interface mthd  implementation
  abstractEnumMthdImpl(person, person2, person3);
  
  //testing default toString method
  defaultToString(person,person2,person3);
  
  //testing equals method
  equalityChk(person,person2,person3);
  
  //invoke toString() on person objects
  System.out.println(person);
  System.out.println(person2);
  System.out.println(person3);
 }
 
 /**
  * This method print values of the enumeration 
  */
 private static void printValues(){
  System.out.println("----Enumeration values-------");
  
  for(EducationDtlEnum data:EducationDtlEnum.values()){
   System.out.println(data);
  }
  System.out.println("---------------------------------------");
 }
 
 /**
  * This method checks whether enum objects are created once 
  * or created for every reference.
  * 
  * @param person
  * @param person2
  * @param person3
  */
 private static void refCheck(Person person,Person person2,Person person3){
  System.out.println("Checking for reference ==");
  System.out.println("---------------------------------------");
  System.out.println(person.getEducationInfo()==(person2.getEducationInfo()));
  System.out.println(person.getEducationInfo()==(person3.getEducationInfo()));
  System.out.println("---------------------------------------");  
 }
 
 /**
  * Here our custom enum has an abstract method print whose implementations are provided
  * by all the enums.We are invoking that method.
  * 
  * @param person
  * @param person2
  * @param person3
  */
 private static void abstractEnumMthdImpl(Person person,Person person2,Person person3){
  System.out.println("Get print implementations");
  System.out.println("------------------------------------");
  person.getEducationInfo().print();
  person2.getEducationInfo().print();
  person3.getEducationInfo().print();
  System.out.println("------------------------------------");  
 }
 
 /**
  * This method invokes the default toString() method of enum
  * 
  * @param person
  * @param person2
  * @param person3
  */
 private static void defaultToString(Person person,Person person2,Person person3){
  System.out.println("Get toString() implementations");
  System.out.println("---------------------------------------");
  System.out.println(person.getEducationInfo().toString());
  System.out.println(person2.getEducationInfo().toString());
  System.out.println(person3.getEducationInfo().toString());
  System.out.println("---------------------------------------");
  
 }
 
 /**
  * This method invokes the default equals method of enum
  * 
  * @param person
  * @param person2
  * @param person3
  */
 private static void equalityChk(Person person,Person person2,Person person3){
  System.out.println("Equality check");
  System.out.println("---------------------------------------");
  System.out.println(person.getEducationInfo().equals(person2.getEducationInfo()));
  System.out.println(person.getEducationInfo().equals(person3.getEducationInfo()));
  System.out.println("---------------------------------------");
  
  
 }

}

Output of the above code

----Enumeration values-------
PG
UG
GRAD
HS
PHD
---------------------------------------
Checking for reference ==
---------------------------------------
true
false
---------------------------------------
Get print implementations
------------------------------------
Person may have doen PHD,MD or similar things.
Person may have doen PHD,MD or similar things.
Person may have done MBA,MCA,MS or similar things
------------------------------------
Get toString() implementations
---------------------------------------
PHD
PHD
PG
---------------------------------------
Equality check
---------------------------------------
true
false
---------------------------------------
Person [educationInfo=PHD, genderEnum=M, incomeGroup=HIG, name=Mr. A]
Person [educationInfo=PHD, genderEnum=F, incomeGroup=HIG, name=Mrs. B]
Person [educationInfo=PG, genderEnum=M, incomeGroup=MIG, name=Mr. C]