Header Ads

ad

Generics in Java

Agenda

  1. Introduction to Generics in Java
  2. Generics classes
  3. Bounded Types
  4. Generic methods & wild card character(?)
  5. Communication with non-generic code
  6. Conclusions

Introduction to Generics in Java

The generics concept in java was introduced in Java 1.5 to deal with type safe objects.

The main objectives of Generics is
  • To provide type safety and
  • To resolve type casting problems.

Case 1 : Type Safety

 String[] names = new String[10];

 s[0] = "Ravi";
 s[1] = "Shiva";

 s[2] = new Integer(10); X 

In the above code, we have declared an array of String types. So, we can add only string type of objects. If we try to add any other types we will get Compile time errors.

So, we can say that Array is type safe because it allows a specific type of objects.

Let's apply the same code in the Collection.


 ArrayList names = new ArrayList();

 names.add("Ravi");
 names.add("Shiva");

 names.add(new Integer(10));

In ArrayList we can add any type of objects. So, It is not type safe.

Array is type safe because we can store only specific type of objects in array but Collection is not type safe because we can add any type of objects in Collection.

For example, If our programing requirement is to store only string type of objects and we choose ArrayList. By mistake if we are trying to add any other type of objects we will not get get compile time error because ArrayList allows different types of objects. But the program may fail at runtime.


Case 2 : Type Casting

 String[] names = new String[10];

 s[0] = "Ravi"
 s[1] = "Shiva"

 String name1 = s[0] //type casting is not required

In the above code snippet we can see while assigning the value of index 0 to name1 variable type casting is not required.

But in the Collection, type casting is mandatory because get method returns Object type. If we do not type cast, we will get runtime exception which is ClassCastException.


 ArrayList names = new ArrayList();

 names.add("Ravi");
 names.add("Shiva");
 names.add(new Integer(10));

 String name1 = (String) names.get(0);//type casting is mandatory


So, to achieve type safety, resolve type casting problems and to detect the bugs at compile time, Sun People introduced Generics in Java 1.5


How to create generic version of ArrayList object.

For example, to hold only String type of objects we can create generic version of ArrayList object is as follows :

 ArrayList<String> names = new ArrayList<String>();


Type Safety in ArrayList through Generics

 ArrayList<String> names = new ArrayList<String>();
 names.add("Ravi");
 names.add("Shiva");

 names.add(new Integer(10)); // compile time error


In the above code, We are getting compile time error if we add Integer type to Generic ArrayList.

Through generics we are getting type safety in Collection.



Communication with non-generic code


Here, we have to discuss 2 things like what will happen if we send 
  1. Generic object to non-generic area and
  2. Non-generic object to generic area.

It is decided by the location, the location where object is currently present based on that behavior of the object is defined.

It means If we send a generic object to non-generic area, it starts behaving like non-generic object.

And if we send a non-generic object to generic area, it starts behaving like generic object.


Example 1: Sending generic object to non-generic area

 public class Test {

public static void m1(ArrayList l) {
l.add(10);
l.add(10.5);
l.add(true);
}

public static void main(String[] args) {
ArrayList<String> al=new ArrayList<String>();
al.add("Manoj");
al.add("Ashok");

//l.add(10); compiler does not allow it

m1(al);
System.out.println(al);
}
}


Output :-
 [Manoj, Ashok, 10, 10.5, true]



Example 2: Sending non-generic object to generic area


 public class Test {

public static void m1(ArrayList<String> l) {
l.add("Ashok");
//l.add(10); compiler does not allow it
}

public static void main(String[] args) {
ArrayList al=new ArrayList();
al.add("Manoj");
al.add(true);
al.add(10);

m1(al);
System.out.println(al);
}
}



Output :-
 [Manoj, true, 10, Ashok]




Type safety & type casting both are applicable at compile time. Hence generics concept also applicable only at compile time but not at run time.

At the time of compilation, as the last step generics syntax will be removed and hence for JVM, generics syntax will not be available at run time.

Let's take an example to understand it.

public class Test 
{
public void m1(ArrayList<String> al) 
{
}

public void m1(ArrayList<Integer> al)
{
}
}



Output:-
Test.java:9: error: name clash: m1(ArrayList<Integer>) and m1(ArrayList<String>) have the same erasure
        public void m1(ArrayList<Integer> al)
                    ^
1 error

If we compile above class we get compile time error, because at the time of compilation, as last step Generics syntax is removed.

So after removal of generics, the above code becomes as follows

public class Test 
{
public void m1(ArrayList al) 
{
}
public void m1(ArrayList al)
{
}
}

And hence both the methods have same signature it throws compile time error.




 ArrayList al = new ArrayList<String>();
 al.add(10);
 al.add(10.5);
 al.add(true);

 System.out.println(al);


Output :-
 [10, 10.5, true]



 ArrayList l = new ArrayList<String>();
 ArrayList l = new ArrayList<Integer>();
 ArrayList l = new ArrayList<Double>();
 ArrayList l = new ArrayList();
All above 4 declarations are equal.



 ArrayList<String> l = new ArrayList<String>();
 ArrayList<String> l = new ArrayList();

Both declarations are equal.


At compile time

The following 3 steps take place:
  1. Compile the code normally by considering generics syntax.
  2. Remove generic syntax
  3. Compile the resultant code.





No comments