Author: saqibkhan

  • Type Erasure

    Generics are used for tighter type checks at compile time and to provide a generic programming. To implement generic behaviour, java compiler apply type erasure. Type erasure is a process in which compiler replaces a generic parameter with actual class or bridge method. In type erasure, compiler ensures that no extra classes are created and there is no runtime overhead.

    Type Erasure rules

    • Replace type parameters in generic type with their bound if bounded type parameters are used.
    • Replace type parameters in generic type with Object if unbounded type parameters are used.
    • Insert type casts to preserve type safety.
    • Generate bridge methods to keep polymorphism in extended generic types.
  • Guidelines for Wildcard Use

    Wildcards can be used in three ways −

    • Upper bound Wildcard − ? extends Type.
    • Lower bound Wildcard − ? super Type.
    • Unbounded Wildcard − ?

    In order to decide which type of wildcard best suits the condition, let’s first classify the type of parameters passed to a method as in and out parameter.

    • in variable − An in variable provides data to the code. For example, copy(src, dest). Here src acts as in variable being data to be copied.
    • out variable − An out variable holds data updated by the code. For example, copy(src, dest). Here dest acts as in variable having copied data.

    Guidelines for Wildcards.

    • Upper bound wildcard − If a variable is of in category, use extends keyword with wildcard.
    • Lower bound wildcard − If a variable is of out category, use super keyword with wildcard.
    • Unbounded wildcard − If a variable can be accessed using Object class method then use an unbound wildcard.
    • No wildcard − If code is accessing variable in both in and out category then do not use wildcards.

    Example

    Following example illustrates the above mentioned concepts.

    package com.tutorialspoint;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class GenericsTester {
    
       //Upper bound wildcard
       //in category
       public static void deleteCat(List<? extends Cat> catList, Cat cat) {
    
      catList.remove(cat);
      System.out.println("Cat Removed");
    } //Lower bound wildcard //out category public static void addCat(List<? super RedCat> catList) {
      catList.add(new RedCat("Red Cat"));
      System.out.println("Cat Added");
    } //Unbounded wildcard //Using Object method toString() public static void printAll(List<?> list) {
      for (Object item : list)
         System.out.println(item + " ");
    } public static void main(String[] args) {
      List&lt;Animal&gt; animalList= new ArrayList&lt;Animal&gt;();
      List&lt;RedCat&gt; redCatList= new ArrayList&lt;RedCat&gt;();
      //add list of super class Animal of Cat class
      addCat(animalList);
      //add list of Cat class
      addCat(redCatList);  
      addCat(redCatList);  
      //print all animals
      printAll(animalList);
      printAll(redCatList);
      Cat cat = redCatList.get(0);
      //delete cat
      deleteCat(redCatList, cat);
      printAll(redCatList); 
    } } class Animal { String name; Animal(String name) {
      this.name = name;
    } public String toString() {
      return name;
    } } class Cat extends Animal { Cat(String name) {
      super(name);
    } } class RedCat extends Cat { RedCat(String name) {
      super(name);
    } } class Dog extends Animal { Dog(String name) {
      super(name);
    } }

    This will produce the following result −

    Cat Added
    Cat Added
    Cat Added
    Red Cat 
    Red Cat 
    Red Cat 
    Cat Removed
    Red Cat 
    
  • Lower Bounded Wildcards

    The question mark (?), represents the wildcard, stands for unknown type in generics. There may be times when you’ll want to restrict the kinds of types that are allowed to be passed to a type parameter. For example, a method that operates on numbers might only want to accept instances of Integer or its superclasses like Number.

    To declare a lower bounded Wildcard parameter, list the ?, followed by the super keyword, followed by its lower bound.

    Example

    Following example illustrates how super is used to specify an lower bound wildcard.

    package com.tutorialspoint;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class GenericsTester {
    
       public static void addCat(List<? super Cat> catList) {
    
      catList.add(new RedCat());
      System.out.println("Cat Added");
    } public static void main(String[] args) {
      List&lt;Animal&gt; animalList= new ArrayList&lt;Animal&gt;();
      List&lt;Cat&gt; catList= new ArrayList&lt;Cat&gt;();
      List&lt;RedCat&gt; redCatList= new ArrayList&lt;RedCat&gt;();
      List&lt;Dog&gt; dogList= new ArrayList&lt;Dog&gt;();
      //add list of super class Animal of Cat class
      addCat(animalList);
      //add list of Cat class
      addCat(catList);
      //compile time error
      //can not add list of subclass RedCat of Cat class
      //addCat(redCatList);
      //compile time error
      //can not add list of subclass Dog of Superclass Animal of Cat class
      //addCat.addMethod(dogList); 
    } } class Animal {} class Cat extends Animal {} class RedCat extends Cat {} class Dog extends Animal {}

    This will produce the following result −

    Cat Added
    Cat Added
    
  • Unbounded Wildcards

    The question mark (?), represents the wildcard, stands for unknown type in generics. There may be times when any object can be used when a method can be implemented using functionality provided in the Object class or When the code is independent of the type parameter.

    To declare a Unbounded Wildcard parameter, list the ? only.

    Example

    Following example illustrates how extends is used to specify an unbounded wildcard.

    package com.tutorialspoint;
    
    import java.util.Arrays;
    import java.util.List;
    
    public class GenericsTester {
       public static void printAll(List<?> list) {
    
      for (Object item : list)
         System.out.println(item + " ");
    } public static void main(String args[]) {
      List&lt;Integer&gt; integerList = Arrays.asList(1, 2, 3);
      printAll(integerList);
      List&lt;Double&gt; doubleList = Arrays.asList(1.2, 2.3, 3.5);
      printAll(doubleList);
    } }

    This will produce the following result −

    Output

    1 
    2 
    3 
    1.2 
    2.3 
    3.5 
    
  • Upper Bounded Wildcards

    The question mark (?), represents the wildcard, stands for unknown type in generics. There may be times when you’ll want to restrict the kinds of types that are allowed to be passed to a type parameter. For example, a method that operates on numbers might only want to accept instances of Number or its subclasses.

    To declare a upper bounded Wildcard parameter, list the ?, followed by the extends keyword, followed by its upper bound.

    Example

    Following example illustrates how extends is used to specify an upper bound wildcard.

    package com.tutorialspoint;
    
    import java.util.Arrays;
    import java.util.List;
    
    public class GenericsTester {
    
       public static double sum(List<? extends Number> numberlist) {
    
      double sum = 0.0;
      for (Number n : numberlist) sum += n.doubleValue();
      return sum;
    } public static void main(String args[]) {
      List&lt;Integer&gt; integerList = Arrays.asList(1, 2, 3);
      System.out.println("sum = " + sum(integerList));
      List&lt;Double&gt; doubleList = Arrays.asList(1.2, 2.3, 3.5);
      System.out.println("sum = " + sum(doubleList));
    } }

    This will produce the following result −

    Output

    sum = 6.0
    sum = 7.0
    
  • Map

    Java has provided generic support in Map interface.

    Syntax

    Set<T> set = new HashSet<T>();
    

    Where

    • set − object of Set Interface.
    • T − The generic type parameter passed during set declaration.

    Description

    The T is a type parameter passed to the generic interface Set and its implemenation class HashSet.

    Learn Java in-depth with real-world projects through our Java certification course. Enroll and become a certified expert to boost your career.

    Example

    Create the following java program using any editor of your choice.

    package com.tutorialspoint;
    
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    
    public class GenericsTester {
       public static void main(String[] args) {
    
    
      Map&lt;Integer,Integer&gt; integerMap 
         = new HashMap&lt;Integer,Integer&gt;();
      integerMap.put(1, 10);
      integerMap.put(2, 11);
      Map&lt;String,String&gt; stringMap = new HashMap&lt;String,String&gt;();
    
      stringMap.put("1", "Hello World");
      stringMap.put("2","Hi World");
      System.out.printf("Integer Value :%d\n", integerMap.get(1));
      System.out.printf("String Value :%s\n", stringMap.get("1"));
      // iterate keys.
      Iterator&lt;Integer&gt; integerIterator   = integerMap.keySet().iterator();
      while(integerIterator.hasNext()) {
         System.out.printf("Integer Value :%d\n", integerIterator.next());
      }
      // iterate values.
      Iterator&lt;String&gt; stringIterator   = stringMap.values().iterator();
      while(stringIterator.hasNext()) {
         System.out.printf("String Value :%s\n", stringIterator.next());
      }
    } }

    This will produce the following result −

    Output

    Integer Value :10
    String Value :Hello World
    Integer Value :1
    Integer Value :2
    String Value :Hello World
    String Value :Hi World
    
  • Set

    Java has provided generic support in Set interface.

    Syntax

    Set<T> set = new HashSet<T>();
    

    Where

    • set − object of Set Interface.
    • T − The generic type parameter passed during set declaration.

    Description

    The T is a type parameter passed to the generic interface Set and its implemenation class HashSet.

    Learn Java in-depth with real-world projects through our Java certification course. Enroll and become a certified expert to boost your career.

    Example

    Create the following java program using any editor of your choice.

    package com.tutorialspoint;
    
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Set;
    
    public class GenericsTester {
       public static void main(String[] args) {
    
    
      Set&lt;Integer&gt; integerSet = new HashSet&lt;Integer&gt;();
      integerSet.add(Integer.valueOf(10));
      integerSet.add(Integer.valueOf(11));
      Set&lt;String&gt; stringSet = new HashSet&lt;String&gt;();
      stringSet.add("Hello World");
      stringSet.add("Hi World");
      for(Integer data: integerSet) {
         System.out.printf("Integer Value :%d\n", data);
      }
      Iterator&lt;String&gt; stringIterator = stringSet.iterator();
      while(stringIterator.hasNext()) {
         System.out.printf("String Value :%s\n", stringIterator.next());
      }
    } }

    This will produce the following result −

    Output

    Integer Value :10
    Integer Value :11
    String Value :Hello World
    String Value :Hi World
    
  • List

    Java has provided generic support in List interface.

    Syntax

    List<T> list = new ArrayList<T>();
    

    Where

    • list − object of List interface.
    • T − The generic type parameter passed during list declaration.

    Description

    The T is a type parameter passed to the generic interface List and its implemenation class ArrayList.

    Learn Java in-depth with real-world projects through our Java certification course. Enroll and become a certified expert to boost your career.

    Example

    Create the following java program using any editor of your choice.

    package com.tutorialspoint;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    public class GenericsTester {
       public static void main(String[] args) {
    
    
      List&lt;Integer&gt; integerList = new ArrayList&lt;Integer&gt;();
      integerList.add(Integer.valueOf(10));
      integerList.add(Integer.valueOf(11));
      List&lt;String&gt; stringList = new ArrayList&lt;String&gt;();
      stringList.add("Hello World");
      stringList.add("Hi World");
      System.out.printf("Integer Value :%d\n", integerList.get(0));
      System.out.printf("String Value :%s\n", stringList.get(0));
      for(Integer data: integerList) {
         System.out.printf("Integer Value :%d\n", data);
      }
      Iterator&lt;String&gt; stringIterator = stringList.iterator();
      while(stringIterator.hasNext()) {
         System.out.printf("String Value :%s\n", stringIterator.next());
      }
    } }

    This will produce the following result −

    Output

    Integer Value :10
    String Value :Hello World
    Integer Value :10
    Integer Value :11
    String Value :Hello World
    String Value :Hi World
    
  • Multiple Bounds

    A type parameter can have multiple bounds.

    Syntax

    public static <T extends Number & Comparable<T>> T maximum(T x, T y, T z)
    

    Where

    • maximum − maximum is a generic method.
    • T − The generic type parameter passed to generic method. It can take any Object.

    Description

    The T is a type parameter passed to the generic class Box and should be subtype of Number class and must implments Comparable interface. In case a class is passed as bound, it should be passed first before interface otherwise compile time error will occur.

    Learn Java in-depth with real-world projects through our Java certification course. Enroll and become a certified expert to boost your career.

    Example

    Create the following java program using any editor of your choice.

    package com.tutorialspoint;
    
    public class GenericsTester {
       public static void main(String[] args) {
    
      System.out.printf("Max of %d, %d and %d is %d\n\n", 
         3, 4, 5, maximum( 3, 4, 5 ));
      System.out.printf("Max of %.1f,%.1f and %.1f is %.1f\n\n",
         6.6, 8.8, 7.7, maximum( 6.6, 8.8, 7.7 ));
    } public static <T extends Number
      &amp; Comparable&lt;T&gt;&gt; T maximum(T x, T y, T z) {
      T max = x;      
      if(y.compareTo(max) &gt; 0) {
         max = y;   
      }
      if(z.compareTo(max) &gt; 0) {
         max = z;                    
      }
      return max;      
    } // Compiler throws error in case of below declaration /* public static <T extends Comparable<T>
      &amp; Number&gt; T maximum1(T x, T y, T z) {
      T max = x;      
      if(y.compareTo(max) &gt; 0) {
         max = y;   
      }
      if(z.compareTo(max) &gt; 0) {
         max = z;                    
      }
      return max;   
    }*/ }

    This will produce the following result −

    Output

    Max of 3, 4 and 5 is 5
    
    Max of 6.6,8.8 and 7.7 is 8.8
    
  • Bounded Type Parameters

    There may be times when you’ll want to restrict the kinds of types that are allowed to be passed to a type parameter. For example, a method that operates on numbers might only want to accept instances of Number or its subclasses. This is what bounded type parameters are for.

    To declare a bounded type parameter, list the type parameter’s name, followed by the extends keyword, followed by its upper bound.

    Example

    Following example illustrates how extends is used in a general sense to mean either “extends” (as in classes) or “implements” (as in interfaces). This example is Generic method to return the largest of three Comparable objects −

    public class MaximumTest {
       // determines the largest of three Comparable objects
       
       public static <T extends Comparable<T>> T maximum(T x, T y, T z) {
    
      T max = x;   // assume x is initially the largest
      
      if(y.compareTo(max) &gt; 0) {
         max = y;   // y is the largest so far
      }
      
      if(z.compareTo(max) &gt; 0) {
         max = z;   // z is the largest now                 
      }
      return max;   // returns the largest object   
    } public static void main(String args[]) {
      System.out.printf("Max of %d, %d and %d is %d\n\n", 
         3, 4, 5, maximum( 3, 4, 5 ));
      System.out.printf("Max of %.1f,%.1f and %.1f is %.1f\n\n",
         6.6, 8.8, 7.7, maximum( 6.6, 8.8, 7.7 ));
      System.out.printf("Max of %s, %s and %s is %s\n","pear",
         "apple", "orange", maximum("pear", "apple", "orange"));
    } }

    This will produce the following result −

    Output

    Max of 3, 4 and 5 is 5
    
    Max of 6.6,8.8 and 7.7 is 8.8
    
    Max of pear, apple and orange is pear