Java Generics part 2

In the previous post, we saw the basic introduction to generics. In this post we will dive deeper into generics concept and try to cement our understanding how generics is implemented internally.

Generic Classes

Until 1.4 version, a non-generic version of ArrayList class is declared as:

// Till 1.4 version
class ArrayList{
    // Other methods
    add(Object o){
        // Body
    }
    Object get(int index){
        // Body of method
    }
}

The argument to add() is Object and therefore we can add any type of object to the ArrayList. Because of this we are missing type-safety.

The return type of get() is Object and therefore at the time of retrieval we have to perform type-casting.

In 1.5 version, a generic version of ArrayList class is declared as:

// Here T is type parameter
class ArrayList<T>{
    add(T t){
        // Body
    }
    T get(int index){
        // Body
    } 
}

NOTE: Based on our runtime requirement, T will be replaced with our provided type.

To hold only String type of Object a generic version of ArrayList object can be created as:

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

For this requirement, compiler-considered version of ArrayList class is as:

class ArrayList<String>{
    add(String t){
        // Body
    }
    String get(int index){
        // Body
    } 
}

The argument to add() method is String type and therefore, we can add only String type of objects. If we trying to add any other type by mistake, we will get compile-time error.

al.add("Jim");
al.add(new Integer(10)); // CE: Cannot find symbol add(java.lang.Integer) location: class ArrayList<String>