Recent Posts

Wednesday, 3 August 2016

Generics Tutorial


Introduction
     Array objects are by default typesafe. i.e we declare String Array we can insert only String Objects. By Mistake if we r trying to insert any other elements we will get compile time error.
E.g
String [] str = new String[100];
str[0] = "Ashok";
str[1] = 10; // C.E
     But Collection objects are not typesafe by default. If our requirement is to add only String objects to the ArrayList , By mistake if we r trying to insert any other element we won’t get any compile time error.
ArrayList list = new ArrayList();
list.add(“Ashok”);
list.add(new Integer(10)); // No Compile Time Error.
     While retrieving Array elements there is no need to perform typecasting.
String name = s[0]; // No typecasting required here.
     But while retrieving the elements from ArrayList compulsory we should perform typecasting
String name = list.get(0); // C.E
String name = (String)list.get(0);
To resolve the above 2 problems (typesafety, typecasting) sun people introduced generics concept in the 1.5 version.If we want to create ArrayList object to hold any String Objects we have to define as follows.
ArrayList<String> list = new ArrayList<String>();
     For this ArrayList we have to add only String objects. By mistake if we r trying to add any other type we will get compile time error.
list.add(“valid”);
list.add(new Integer(10)); // C.E: Can’t find the symbol add(Integer)
     At the time of retrieval no need to perform any typecasting.
String name = list.get(0); // No typecasting is required.
     Hence by using generics we can provide typesafety and we can resolve typecasting problems.

   By using generics we can define parameter for the collection. These parameterized collection classes are nothing but “Generic collection classes”. Polymorphism concept is not applicable for the parameter type but applicable for basetype
List<String> list = new ArrayList<String>(); // Fine

List<Object> list = new ArrayList<String>(); // C.E: 
                                             Incompatable Types
                                             Found:ArrayList<String>
                                             Required :List<Object>
The type parameter must be object type(any class or interface name). we can’t apply generic concept for primitive datatype. E.g
ArrayList<int> list = new ArrayList<int>(); // C.E: 
                                            unexpected type found : int
                                            Required : Integer
Generic Classes
     Until 1.4 version we have ArrayList class with the declarations as follows.
class ArrayList {
   add(Object o);
   Object get(int index);
}
add method contain Object as argument, hence we can add any kind of object.

     As a result we can’t get any type safety. The return type of get() method is object hence at the time of retrieval we should perform typecasting.
     But in the 1.5 version we have generic ArrayList class with the definition as follows
class ArrayList<T> {
   add(T t);
   T get(int);
}
     Based on runtime requirement the corresponding version of ArrayList will loaded.
ArrayList<String> list = new ArrayList<String>();
     For the following declarations the corresponding loaded class is
class ArrayList<String> {
   add(String);
   String get(int);
}
     The argument to the add method is String hence we should add only String Object as the result we will get type safety. The return type of get() method is String. Hence at the time of retrieval no need to perform typecasting.

     We can define our own generic classes also
class gen<T> {
   T obj;

   gen(T ob) {
      this.obj = ob;
   }

   public void show() {
      System.out.println("The type of Object is : " + obj.getClass().getName());
   }

   public T getOb() {
      return obj;
   }
}

public class MyGenerics {
   public static void main(String[] args) {
      gen<String> gen1 = new gen<String>("Ashok");
      gen1.show();
      System.out.println(gen1.getOb());
      gen<Integer> gen2 = new gen<Integer>(10);
      gen2.show();
      System.out.println(gen2.getOb());
   }
}

Output
The type of Object is : java.lang.String
Ashok
The type of Object is : java.lang.Integer
10
BoundedTypes
     We can bound the type parameter for a particular range. Such type of types is called bounded types. We can achieve this by using extends keyword.
E.g
class Gen<T> {

}
     Here we can pass any types as the type parameter and there are no restrictions.
Gen<String> g1 = new Gen<String>();
Gen<Integer> g2 = new Gen<Integer>();
E.g
Class Gen<T extends X>
      If ‘X’ is a class then any type which is the child class of ‘X’ is allowed as the type parameter.
      If ‘X’ is an interface then any type which is the implementation class of ‘X’ is allowed as the type parameter.
E.g
class Gen<T extends Number> {

}
     In this case as the type parameter we can take either number or it’s child classes.
Gen<Integer> g1 = new Gen<Integer>();// Fine
Gen<String> g2 = new Gen<String>(); // C.E
     Because type parameter String is not with in it’s bound
class Gen<T extends Runnable> {

}
     In this case as the type parameter we can take any implementation class of Runnable interface.
Gen<Thread> t1 = new Gen<Thread>(); // Fine
Gen<String> t2 = new Gen<String>(); // C.E
     Because String is not implementation class of Runnable interface.
     In generics we have only extends keyword and there is no implements keyword. It’s purpose is also survived by using extends keyword only.
E.g
class Gen<T extends Number> {
   T obj;
   Gen(T obj) {
     this.obj = obj;
   }
   void show() {
      System.out.println("The int value is :" + ob.intValue());
   }
}
public class MyGeneric {
   public static void main(String arg[]) {
      Gen<Integer> t1 = new Gen<Integer>(new Integer(10));
      t1.show();
      Gen<Double> t2 = new Gen<Double>(10.5);
      t2.show();
      Gen<String> t3 = new Gen<String>("Ashok"); // C.E
      t3.show();
   }
}
Generic Methods
1. m1(ArrayList<String>)
     It is applicable for ArrayList of only String type.

2. m1(ArrayList<? extends x> l)
     Here if ‘x’ is a class then this method is applicable for ArrayList of either x or it’s child classes.
     If ‘x’ is an interface then this method is applicable for ArrayList of any implementation class of x

3. m1(ArrayList <? Super x> l)
    If ‘x’ is a class then this method is applicable for ArrayList of either x or it’s super classes.
  If ‘x’ is an interface then this method is applicable for ArrayList of any super classes of implemented class of x.

4. m1(ArrayList <?> l)
    This method is applicable for ArrayList of any type.
    In the method declaration if we can use ‘?’ in that method we are not allowed to insert any element except null. Because we don’t know exactly what type of object is coming.
E.g
import java.util.ArrayList;

class MyGenericMethod {
   public static void main(String arg[]) {
      ArrayList<String> list1 = new ArrayList<String>();
      list1.add("A");
      list1.add("B");
      list1.add("C");
      list1.add("D");
      m1(list1);
 
      ArrayList<Integer> list2 = new ArrayList<Integer>();
      list2.add(10);
      list2.add(20);
      list2.add(30);
      list2.add(40);
      m1(list2);
   }

   public static void m1(ArrayList<?> list) {
      // list.add("D"); C.E: Because we can’t expect what type of value will come
      list.remove(1);
      list.add(null);
      System.out.println(l);
   }
}

Output
[A, C, D, null]
[10, 30, 40, null]
Note
     Generics is the concept applicable only at compile time to provide type safety, at runtime there is no generic concept at all.

Next Tutorial  Threads and Concurrency Tutorial

Previous Tutorial  Collection Framework Tutorial Part 5

No comments:

Post a Comment