Generics

Generics

Java Generics features were introduced from Java Se 5 onwards. Before Java 5, we can store any type of objects in collection i.e. non generic. With inclusion of Generics we need to store only specific type of objects only.

Let’s look at the benefits of generics

  • Compile time checking: Generics allows you to check any errors at compile time itself, as fixing compile time errors is easier than fixing them at runtime.
  • List<Integer> li = new ArrayList<Integer>();
    li.add("generics");  //Compile Time Error
    li.add(11);
  • Elimination of casts:

Without generics requires casting:

List list = new ArrayList();
list.add("hello");
String s = (String) list.get(0);

Using  generics, the code does not require casting:

List<String> list = new ArrayList<String>();
list.add("hello");
String s = list.get(0);   // no cast
  • By using generics, programmers can implement generic algorithms that work on collections of different types, can be customized, and are type safe and easier to read

Basic Syntax is

Class or Interface<Type>List<Integer>

Generics in Collection:

Let’s see with an example how generics can be used in List

List<String> li = new ArrayList<String>();
li.add("generics");
li.add("Collection");
System.out.println("Generics in collections: "+li.get(1));
Iterator<String>it = li.iterator();
while(it.hasNext()){
       System.out.println(it.next());
}

From Java se 7 onwards (Type Inference), no need to mention type explicitly simply we need to replace them with empty set of arguments <> (diamond)

List<String> li = new ArrayList<>();

In the above example, explicitly mentioned which type of object we are going to use in the List i.e. String, which ensures type safety and compile time error checking.

“li.get(1)” for this no need of type casting, compiler automatically knows that List can accepts only String.

Similarly while iterating the list also no need of typecasting for “it.next()”

Will discuss more by taking one more example using Map

In Map (java.util.Map) we specify both Keys and Values as generic

Java 5 features

Java 5 features

Basic Syntax is

Map<K, V> map = new HashMap<K, V>();

Map<Integer, String> map = new HashMap<Integer, String>();

From Java se 7 onwards(Type Inference), no need to mention type explicitly simply we need to replace them with empty set of arguments <> (diamond)

Map<Integer, String> map = new HashMap<>();

Map<Integer, String> map = new HashMap<>();
map.put(1, "Generics");
map.put(2, "Collections");
Iterator key = map.keySet().iterator();
for(Integer i: map.keySet()){
        System.out.println("Key:  "+i+"  Value: "+map.get(i));
}
while(key.hasNext()){
Integer key1 = key.next();
      System.out.println("Key:  "+key1+"  Value: "+map.get(key1));
}
for(Map.Entry<Integer, String>me: map.entrySet()){
       System.out.println("Key:  "+me.getKey()+"  Value: "+me.getValue());
}

We have explicitly mentioned the Key, values types, here in this example we used Integer and String respectively which will prevent most of the run time errors.

No need to type cast while using Iterator “key.next()”, compiler will identify the correct type because of Generics.For Map.Entry also specified types.

Generic Classes

A generic class is defined with the following format:

Classname<T1, T2, …,Tn> {  … }

The type parameter section, delimited by angle brackets (<>), follows the class name. It specifies the type parameters (also called type variables) T1, T2, …, and Tn.

To update the Test class to use generics, you create a generic type declaration by changing the code “public class Test” to “public class Test<T>”. This introduces the type variable, T, that can be used anywhere inside the class.

public class Generics {
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
public static void main(String[] args) {
     Generics ge = new Generics();
     ge.set(123);
     System.out.println("generics class:: "+ge.get());
}

From Java se 7 onwards (Type Inference), no need to mention type explicitly simply we need to replace them with empty set of arguments <> (diamond)

Generics<Integer> ge = new Generics<>();

As you can see, all occurrences of Object are replaced by T. A type variable can be any non-primitive type you specify: any class type, any interface type, any array type, or even another type variable.

This same technique can be applied to create generic interfaces.

Type Parameters

The most commonly used type parameter names are:

T – Type

E – Element

K – Key

N – Number

V – Value

Generic Methods

We can apply this generics to methods and constructor also, check this example

public static void genericMethod(List list){
for(T t: list){
      System.out.println(t);
}
}
List li = new ArrayList<>();
li.add("generics");
li.add("Collection");
genericMethod(li);

‘T’ is any type, later if we want to send Integer type we can simply declare like this

List<Integer> li = new ArrayList<>();

Wildcard in Java Generics

The question mark (?) symbol represents wildcard element. It means any type. If we write <? extends Number>, it means any child class of Number e.g. Integer, Float, double etc. Now we can call the method of Number class through any child class object.

 

One thought on “Generics

Leave a Reply

Your email address will not be published. Required fields are marked *