Generics in Java

Introduction to Generic methods and classes in Java

Generics in Java allow you to write code that is more reusable, flexible, and type-safe. Generics allow you to specify the types of data that your code will work with, which can help to prevent errors and make your code more efficient.

Generics are declared using type parameters. Type parameters are placeholders for the types of data that your code will work with. When you use a generic method or class, you specify the actual types of data that you want to use when you call the method or instantiate the class.

For example, the following code declares a generic method called `swap()` that can be used to swap any two values, regardless of their type:


public static  void swap(T x, T y) {
  T temp = x;
  x = y;
  y = temp;
}

To use the `swap()` method, you would specify the types of data that you want to swap when you call the method. For example, the following code calls the `swap()` method to swap two integers:


int a = 10;
int b = 20;

swap(a, b);

System.out.println(a); // 20
System.out.println(b); // 10

Generics can also be used to declare generic classes. For example, the following code declares a generic class called `MyStack`:


public class MyStack {
  private LinkedList stack; 

  public MyStack() {
    this.stack = new LinkedList<>();
  }

  public void push(T element) {
    this.stack.push(element);
  }

  public T pop() {
    return this.stack.pop();
  }

  public boolean isEmpty() {
    return this.stack.isEmpty();
  }
}

This class can be used to store a stack of any type of data. To use the `MyStack` class, you would specify the type of data that you want to store when you instantiate the class. For example, the following code instantiates a `MyStack` class to store a stack of integers:


MyStack stack = new MyStack<>();

Generics offer a number of benefits, including:

  • Reusability: Generic code can be reused with different types of data without having to duplicate your code. This can save you time and effort, and it can also make your code more maintainable.
  • Flexibility: Generic code can be used with a wider range of data types, making your code more flexible. This can be useful if you are not sure what types of data you will need to work with in the future.
  • Type safety: Generic code can help to prevent type errors. This can make your code more reliable and less prone to bugs.
  • Performance: Generic code can improve the performance of your code by eliminating the need for boxing and unboxing.

Exercises

Code without using a generic method for displaying data of different data types


import java.io.*;
import java.util.Scanner;
public class Satish20BCE001{
  
  public static void main(String[] args) throws IOException{
    display(1);
    display("satish");
    display(2.3);
  
  }

  public static void display(int element)
  {
    System.out.println(element);
  }
  
  public static void display(String element)
  {
    System.out.println(element);
  }
  
  public static void display(double element)
  {
    System.out.println(element);
  }

}  

Demo code using a generic method for displaying data of different data types


  import java.util.Scanner;

  public class Satish20BCE001{
  public static void main(String[] args) throws InterruptedException{
    
    display(1);
    display("satish");
    display(2.3);
  
  }
  
  public static <T> void display(T element)
  {
    System.out.println(element);
  }
  } 

Demo code for a generic method taking multiple arguments of the same type


  package javaprogrammingdemo;
  public class javalabclass{
    public static void main(String args[]) {
      
      display(10.23F,123.0F);
    }
    
    public static <T> void display(T x,T y)
    {
      System.out.println("The first element is "+x);
      System.out.println("The first element is "+y);
    }
  } 

Demo Code for a generic method taking multiple arguments of different types


  package javaprogrammingdemo;
  public class javalabclass{
    public static void main(String args[]) {
      
      display(10.23F,"satish");
    }
    
    public static <T,U> void display(T x,U y)
    {
      System.out.println("The first element is "+x);
      System.out.println("The first element is "+y);
    }
  } 

Code for demonstrating the use of Generic class in java


  //code without using generic classes
  package javaprogrammingdemo;
  public class javalabclass{
    public static void main(String args[]) {
      test obj = new test("satish",123);
      obj.display();
    }   
  }
  
  class test
  {
  String element1;
  int element2;
  
  public test(String element1, int element2) {
    this.element1 = element1;
    this.element2 = element2;
  }
  
  public void display()
  {
    System.out.println(this.element1);
    System.out.println(this.element2);
  }
  }
  
  //converting the code given above to use a generic class 
  package javaprogrammingdemo;
  public class javalabclass{
      public static void main(String args[]) {
       test<String,Integer> obj = new test<String,Integer>("satish",123);
       obj.display();
      }   
  }
  
  class test<T,U>
  {
    T element1;
    U element2;
    
    public test(T element1, U element2) {
      this.element1 = element1;
       this.element2 = element2;
    }
    
    public void display()
    {
      System.out.println(this.element1);
      System.out.println(this.element2);
    }
  } 

Write a Generic method that will receive an array of objects and print the data for the objects. Create an array of students and course objects using the classes given below. Pass the array of objects to generic method. Display the data members of the objects from within the array. The classes are given below


class students
{
	String name;
	String address;
	
	public students(String name, String address) {
		this.name = name;
		this.address = address;
	}	
	
}

class course
{
	String coursename;
	int courseid;
	
	public course(String coursename, int courseid) {
		this.coursename = coursename;
		this.courseid = courseid;
	}	
}

Solution for the problem is given below

package javaprogrammingdemo; public class javalabclass{ public static void main(String args[]) { //Generic method to handle an array of objects students s[] = new students[2]; s[0]=new students("satish","vellore"); s[1]=new students("ram","chennai"); course c[] = new course[2]; c[0]=new course("java",123); c[1]=new course("os",321); display(s); display(c); } public static <T> void display(T s[]) { for(T k:s) { if(k instanceof students) { System.out.println(((students)k).name+((students)k).address); } if(k instanceof course) { System.out.println(((course)k).coursename+((course)k).courseid); } } } } class students { String name; String address; public students(String name, String address) { this.name = name; this.address = address; } } class course { String coursename; int courseid; public course(String coursename, int courseid) { this.coursename = coursename; this.courseid = courseid; } }

Demo code for use of extends keyword in a generic method


  package javaprogrammingdemo;
  public class javalabclass{
    public static void main(String args[]) {
      
      //Generic method to handle an array of objects 
      Integer a[] = {1,2,3,4};
      display(a);
      
    }
  public static <T extends Number> void display(T s[])
  {
    for(T k:s)
    {
      System.out.println(k);
    }
  }
  } 

Exercise on creating a Generic class with an array of Generic Objects. The class will have the following methods
parameterized constructor for initializing the elements of the generic class
display method to display the elements of the generic class
sort method that will receive an array of generic objects and sort them. The result will be displayed from within the sort method
The following classes can be used for creating an array of objects

class employee
{
	String empid;
	String name;
	String address;
	public employee(String empid, String name, String address) {
		super();
		this.empid = empid;
		this.name = name;
		this.address = address;
	}
	
}

class course
{
	String courseid;
	String coursename;
	
	public course(String courseid, String coursename) {
		super();
		this.courseid = courseid;
		this.coursename = coursename;
	}
} 

Solution to the given problem


import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
public class demoClass{
    public static void main(String args[]) {
    	employee e[] = new employee[2];
    	e[0] = new employee("124","Satish","Vellore");
    	e[1] = new employee("123","Ram","Chennai");
    	test<String,employee> t = new test<String,employee>("Satish",e);
    	t.display();
    	test.sort(e);
    }
} 

class test<T,U>
{
	T element1;
	U[] obj;
	
	public test(T element1, U obj[]) 
	{
        this.element1=element1;
        if(obj[0] instanceof employee)
        {
        	this.obj = obj.clone();
        }
        if(obj[0] instanceof course)
        {
        	this.obj = obj.clone();
        }
     }
	
	public void display()
	{
		for(U ele : this.obj)
		{
			if(ele instanceof employee)
			{
				System.out.println(((employee) ele).empid + ((employee) ele).name + ((employee) ele).address);
			}
			if(ele instanceof course)
			{
				System.out.println(((course) ele).courseid);
				System.out.println(((course) ele).coursename);
			}
		}
	}
	
	public static <U> void sort(U obj[]){
        if(obj[0] instanceof employee)
        {
            for(int i=0;i<obj.length-1;i++)
            {
                for(int j=0;j<obj.length-1-i;j++)
               {
                    if(((employee)obj[j]).empid.compareTo(((employee)obj[j+1]).empid)>0)
                    {
                        U temp=obj[j];
                        obj[j]=obj[j+1];
                        obj[j+1]=temp;
                    }
                }
            }
            for(U ele : obj)
    		{
    				System.out.println(((employee) ele).empid + ((employee) ele).name + ((employee) ele).address);
    		}
        }
        else if(obj[0] instanceof course)
       {
            for(int i=0;i<obj.length-1;i++)
           {
                for(int j=0;j<obj.length-1-i;j++)
                {
                    if(((course)obj[j]).courseid.compareTo(((course)obj[j+1]).courseid)>0)
                    {
                        U temp=obj[j];
                        obj[j]=obj[j+1];
                        obj[j+1]=temp;
                    }
                }
            }
            for(U ele : obj)
			{
				System.out.println(((course) ele).courseid);
				System.out.println(((course) ele).coursename);
			}
        }
        
    }
}

class employee
{
	String empid;
	String name;
	String address;
	public employee(String empid, String name, String address) {
		super();
		this.empid = empid;
		this.name = name;
		this.address = address;
	}
	
}

class course
{
	String courseid;
	String coursename;
	
	public course(String courseid, String coursename) {
		super();
		this.courseid = courseid;
		this.coursename = coursename;
	}
}

Output
//output from the display method
124SatishVellore
123RamChennai
//output from the sort method
123RamChennai
124SatishVellore