generics

Generic Method Example in Java

In this example, we will be studying about generic methods and how to use the same in our programmes.

Generic method, as the name suggests, is a method that does not specify the Type of its parameters, per se. Rather, it defines a criteria (or a place holder) by which, the method introduces its own type parameters. We will try to understand how Java provides the mechanism for generic methods and look at a few examples on the same topic.
 
 
 

Syntax

Consider the example below :


public static  <T> void sum(List <? extends Number> sumList)
{
	Number sum = 0;
	for (Number n : sumList)
	{
	    sum = sum.doubleValue() + n.doubleValue();
	}
	System.out.println(sum);
}
public static void main(String[] args)
{
	List <Integer> integerList = new ArrayList <>();
	integerList.add(1);
	integerList.add(2);
	integerList.add(3);
	sum(integerList);

	List <Float> floatList = new ArrayList <>();
	floatList.add(1.2f);
	floatList.add(2.2f);
	floatList.add(3.4f);
	sum(floatList);
}

In the above snippet, the method sum accepts a java.util.List object, but the List should be of a class that extends java.lang.Number abstract class. This ensures that we don’t get java.lang.NumberFormatException. In absence of generics, getting the same level of type safety would have been rather messy. We would have had to specifically check the elements for being numerical(so that they could be added).Also, we would have to overload for List of Integers and List of Float/Double.This smart type inference by the Java compiler also helps us avoid using Reflection API, which is both slower and difficult, to understand and run.Reflection is also considered as an anti-pattern as it breaks encapsulation.

Use of Generic Methods in DAO Pattern

In DAO Pattern we may define a generic save method, that persists the instance of a particular class by inferring its type at run time.

package com.javacodegeeks.examples;

public class DatabaseUtility <T>
{

   public T save(T t)
    {
      //save logic here
       return t;
    }
		
     //rest of the class
}

In the same manner we can write generic methods for read, update and delete from database.

Common mistakes to avoid while using Generic Methods

  • Generics, unlike array is invariant. A List of Object is not compatible with a List of String even though Object is the superclass of String.
List<Object> =new ArrayList<String>(); //throws compiler error
  • While re-factoring pre-Java5 code, suppose we change a method, displayCollection
public void displayCollection(Collection c)
{
	Iterator itr = c.iterator();
	for (int i = 0; i<c.size(); i++)
	{
		System.out.println(itr.next());
	}
}

to the following method :

public void displayCollection(Collection c)
{
	for (Object o : c)
	{
	     System.out.println(o);
	}
}

We have made a mistake here! Collection<Object> is not the superclass of all the Collections. The superclass of all the collections is Collection<?>(referred to as collection of unknown type).

The proper refactored method should have been :

public void displayCollection(Collection<?> c)
{
	for (Object o : c)
	{
	     System.out.println(o);
	}
}
  • We cannot create Generic Arrays.
   
   T[] array = new T[];//compiler error!

This is not possible due to type erasure property of Java. The Generic Information gets erased at runtime.If it were allowed, then array store check will pass in cases where it should have failed and thrown ArrayStoreException, because the type information is not available at run-time.

  • PECS

We should not add elements to a generic Collection declared with extends(Producer), we must use super (Consumer) for adding elements to the collection.

public static void sum(List<? super Number> sumList)
{
	sumList.add(new Integer(8));
}

This is easier to remember through PECS Producer extends, Consumer super. This acronym was popularised by Joshua Bloch in Effective Java, 2nd Edition, Item 28 :
The idea is that if the parameter will give you Es then you use the extends keyword, and if the parameter takes the Es then it should take any super-class of the Es.

Multiple Bounds :

We can have our methods parameters extend from multiple types. However, the types should both be concrete class(because java does not support multiple inheritance).

public static <T extends Object & Cloneable> void clone(T t1){...}

In case of multiple bounds, the class name shall appear before interface. The parameter T can extend any number of interfaces.

Conclusion

Here we tried to understand the basics of writing generic methods and how to avoid common mistakes while writing one.

Chandan Singh

Chandan holds a degree in Computer Engineering and is a passionate software programmer. He has good experience in Java/J2EE Web-Application development for Banking and E-Commerce Domains.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button