BeginnersBook

  • Home
  • Java
    • Java OOPs
    • Java Collections
    • Java Examples
  • C
    • C Examples
  • C++
    • C++ Examples
  • DBMS
  • Computer Network
  • Python
    • Python Examples
  • More…
    • jQuery
    • Kotlin
    • WordPress
    • SEO
    • JSON
    • JSP
    • JSTL
    • Servlet
    • MongoDB
    • XML
    • Perl

Generics in Java With Examples

By Chaitanya Singh | Filed Under: java

Generics was introduced in 2004 in Java programming language. Before the introduction of generics, type safety was not available, which caused program to throw errors during runtime. In this tutorial, we will learn why generics are introduced and how to use them in Java. We will also cover wildcard generics with examples.

Why to use Generics in Java?

1. Type Safety

The primary goal of generics is to ensure type safety. As shown below, generics allowed us to check the type mismatch during compile-time rather than run-time. It is nice to check such errors during compile-time. This allows the code to be fixed during compilation process.

Before Java Generics:

//Compiler doesn't know the type of this ArrayList so
//it will allow both the additions and the program will
//throw an error during runtime.
ArrayList arrList = new ArrayList();
arrList.add(101);
arrList.add("hello");

After Java Generics:

//Compiler now knows the type of the ArrayList so it will
//throw compile-time error, if you try to add any element
//to this list which is not an integer
ArrayList<Integer> arrList = new ArrayList<Integer>();
arrList.add(101);
arrList.add("hello"); //this will throw compilation error

2. No Type Casting required

There is no need to use type casting. As compiler already knows the type of the data returned from a collection such as ArrayList, HashMap etc.

ArrayList<String> arrList = new ArrayList<String>();
arrList.add("hello");
arrList.add("bye");

//Before generics, we had to use typecasting 
//like this: String s = (String)arrList.get(1);
String s = arrList.get(1); //no typecasting required

3. Code reusability

Generics allowed a single class or method to be used for multiple data types. For example: We can create an object of ArrayList class for multiple data types, as shown below. Instead of creating an ArrayList class for a single data type, it is created using generics which allowed us to create object of ArrayList class with the desired data type.

//List of Strings
ArrayList<String> names = new ArrayList<String>();

//List of whole numbers
ArrayList<Integer> age = new ArrayList<Integer>();

//List of float numbers
ArrayList<Float> arrList = new ArrayList<Float>();

//List of characters
ArrayList<Character> arrList = new ArrayList<Character>();

...so on

Types of Generics in Java

1. Generic Class

A generic class is declared with a Type parameter. In the following example, we have a generic class Demo, we can use this class in any other class by passing a desired type such as Integer, Float, String etc. You cannot pass primitive data types such as int, float, double etc. as parameter T. To understand the difference between int and Integer, float and Float etc. refer my Java Wrapper Class Tutorial.

//Generic Class
class Demo<T> {
  // T is a type, which can accept any type such as
  //Integer, Double, String etc.
  T obj;
  //Constructor which uses the parameter T to
  //return the object of the passed type
  Demo(T obj) { this.obj = obj; }
  public T getObject() { return this.obj; }
}

// A class that is using generic class
class JavaExample {
  public static void main(String[] args)
  {
    // instance of Integer type
    Demo<Integer> obj1 = new Demo<Integer>(101);
    System.out.println(obj1.getObject());

    // instance of Float type
    Demo<Float> obj2 = new Demo<Float>(15.55f);
    System.out.println(obj2.getObject());

    // instance of String type
    Demo<String> obj3
            = new Demo<String>("BeginnersBook");
    System.out.println(obj3.getObject());

    // instance of Character type
    Demo<Character> obj4
            = new Demo<Character>('A');
    System.out.println(obj4.getObject());
  }
}

Output:

Generic Class Example Output

2. Generic Method

Similar to Generic class, we can have generic methods that can accept different parameter types.

public class JavaExample{
  //generic method
  public static <T> void printElements(T[] arr) {
    for (T item : arr){
      System.out.print(item+" ");
    }
    System.out.println();
  }
  public static void main( String args[] ) {
    Character[] chArr = {'H', 'E', 'L', 'L', 'O'};
    String[] strArr = {"AA", "BB", "CC"};

    System.out.println("Calling generic method with char array");
    printElements(chArr);

    System.out.println("Calling generic method with string array");
    printElements(strArr);
  }
}  

Output:

Generic Method example Output

Type Parameters in Generics

In the above examples, we have seen that the Type parameter T is used. There are several other parameters types that we can use while working with generics. These parameters are:

  • T – Type
  • E – Element
  • K – Key
  • V – Value
  • N – Number

Example: Generics K and V parameters

The HashMap class is declared with the K and V parameters. Here, first parameter in generics is the type of the Key and the second parameter is the type of the Value. In the following example, the HashMap accepts integer key values and string values.

import java.util.*;
public class JavaExample{
  public static void main(String args[]){
    //HashMap <k, V> where K is the type of key
    //and V is the type of value
    HashMap<Integer,String> hMap=new HashMap<>();
    hMap.put(101,"Chaitanya");
    hMap.put(120,"Carl");
    hMap.put(141,"Aditya");

    System.out.println("HashMap elements: ");
    for(Map.Entry mEntry : hMap.entrySet()){
      System.out.print("key: "+ mEntry.getKey() + " & Value: ");
      System.out.println(mEntry.getValue());
    }
  }
}

Output:

HashMap elements: 
key: 101 & Value: Chaitanya
key: 120 & Value: Carl
key: 141 & Value: Aditya

Wildcard in Java Generics

Instead of defining the specific type such as Integer, String, Character, we can use wildcard (represented by question mark ?). There are three types of wild card we can while working with generics:

  • Upper bound wildcards, defined like this <? extends className>
  • Lower bound wildcards <? super className>
  • Non-bounded wildcards <?>

1. Upper bound wildcards

MyClass <? extends AnotherClass>

Class MyClass can accept any parameter type, which is a subclass of AnotherClass. For example: The ArrayList declared like this can accept any parameter type which is a subclass of Number, such as Integer, Double etc.

ArrayList<? extends Number>

Example: In this example, the method addList() can accept any ArrayList that has a the type which is a subclass of class Number.

import java.util.ArrayList;
public class JavaExample {
  private static Double addList(ArrayList<? extends Number> numbers) {
    double sum=0.0; //to store the sum of list elements
    for(Number num:numbers)
    {
      sum += num.doubleValue();
    }
    return sum;
  }

  public static void main(String[] args) {
    ArrayList<Float> listOfNumbers=new ArrayList<Float>();
    listOfNumbers.add(1.5f);
    listOfNumbers.add(2.5f);
    listOfNumbers.add(3.0f);
    System.out.println("Sum of list elements: "+addList(listOfNumbers));

    ArrayList<Integer> listOfInts=new ArrayList<Integer>();
    listOfInts.add(50);
    listOfInts.add(150);
    listOfInts.add(250);
    System.out.println("Sum of list elements: "+addList(listOfInts));
  }
}

Output:

Sum of list elements: 7.0
Sum of list elements: 450.0

2. Lower bound wildcards

MyClass <? super AnotherClass>

Class MyClass can accept any parameter type, which is a superclass of AnotherClass.

Example:

public abstract class Shape {
    public abstract void draw(Canvas c);
}

public class Circle extends Shape {
    private int x, y, radius;
    public void draw(Canvas c) {
        ...
    }
}

public class Rectangle extends Shape {
    private int x, y, width, height;
    public void draw(Canvas c) {
        ...
    }
}

Now, if any method has a lower bound parameter like this:

MyClass<? super Rectangle>

Then, that method can only accept the objects of MyClass, which are declared like this:

MyClass<Rectangle> obj1 = new MyClass<Rectangle>();

OR

MyClass<Shape> obj2 = new MyClass<Shape>();

3. Non-bounded wildcards

MyClass <?>

It can accept any parameter type.

Example:

import java.util.List;
import java.util.ArrayList;
public class JavaExample {
  public static void printElements(List<?> myList)
  {
    for(Object obj:myList)
    {
      System.out.println(obj);
    }
  }
  public static void main(String[] args) {
    List<Integer> list = new ArrayList<>();
    list.add(101);
    list.add(201);
    list.add(301);
    System.out.println("Integer List:");
    printElements(list);
    List<String> list2 = new ArrayList<>();
    list2.add("hello");
    list2.add("hi");
    list2.add("bye");
    System.out.println("String List:");
    printElements(list2);
  }
}

Output:

Integer List:
101
201
301
String List:
hello
hi
bye

Conclusion

In this guide, we learned what are generics and how to use them in Java programming language. We also learned wildcard generics with examples. To learn more such in-depth guides, refer Java Tutorial.

Java Tutorial

Java Introduction

  • Java Index
  • Java Introduction
  • History of Java
  • Features of Java
  • C++ vs Java
  • JDK vs JRE vs JVM
  • JVM - Java Virtual Machine
  • First Java Program
  • Variables
  • Data Types
  • Operators

Java Flow Control

  • Java If-else
  • Java Switch-Case
  • Java For loop
  • Java while loop
  • Java do-while loop
  • Continue statement
  • break statement

Java Arrays

  • Java Arrays

OOPs Concepts

  • OOPs Concepts
  • Constructor
  • Java String
  • Static keyword
  • Inheritance
  • Types of inheritance
  • Aggregation
  • Association
  • Super Keyword
  • Method overloading
  • Method overriding
  • Overloading vs Overriding
  • Polymorphism
  • Types of polymorphism
  • Static and dynamic binding
  • Abstract class and methods
  • Interface
  • Abstract class vs interface
  • Encapsulation
  • Packages
  • Access modifiers
  • Garbage Collection
  • Inner classes
  • Static import
  • Static constructor

Java Exception Handling

  • Exception handling
  • Java try-catch
  • Java throw
  • Java throws
  • Checked and Unchecked Exceptions
  • Jav try catch finally
  • Exception Examples
  • Exception Propagation

Collections Framework

  • Collections in Java
  • Java ArrayList
  • Java LinkedList
  • Java Vector
  • Java HashSet
  • Java LinkedHashSet
  • Java TreeSet
  • Java HashMap
  • Java TreeMap
  • Java LinkedHashMap
  • Java Queue
  • Java PriorityQueue
  • Java Deque
  • Comparable interface
  • Comparator interface
  • Collections Interview Questions

MORE ...

  • Java Scanner Class
  • Java 8 Features
  • Java 9 Features
  • Java Conversion
  • Java Date
  • Java Multithreading
  • Java I/O
  • Java Serialization
  • Java Regex
  • Java AWT
  • Java Swing
  • Java Enum
  • Java Annotations
  • Java main method
  • Java Interview Q

Copyright © 2012 – 2022 BeginnersBook . Privacy Policy . Sitemap