Section 1

Lesson 303.11

Generic and Java Collection Classes Lists, Maps, and Sets

Learning Objectives:

By the end of lesson, learners will be able to:

  • Describe Java Generics.

  • Demonstrate how to create the Generic method, class, and interface.

Section 1

Java Generics

Table of Contents

  • Topic 1: Overview of “Generics<T>.”

  • Topic 2: How to Use Generic.

    • Topic 2a: Generic Method.

    • Topic 2b: Generic Type Class.

    • Topic 2c: Generic Interface.

  • Topic 3: Bounded Types Parameter in Generic.

  • Topic 4: Generic Wildcard.

Topic 1: Overview of “Generics<T>”

  • The Java Generics allow us to create a single class, interface, and method that can be used with different types of data (objects). It allows programmers to create a method or a set of methods that will accept any data type.

  • Data types are to be defined as a generic type in design time, and the actual data type is determined at runtime.

  • In case of a bounded types, we can restrict the data type by using type parameter <T>. Note: Generics do not work with primitive types (int, float, char, etc).

  • In layman’s terms, Generics force type safety in Java language.

Topic 2: How to Use Generic

These are three common ways to use Generic:

  1. Generic Method.

  2. Generic Type Class.

  3. Generic Type Interface.

Topic 2a: Generic Method

  • It is possible to create a generic method in generic class and in regular class. It is also possible to create a static generic method.

  • Syntax:

public class ClassName{
     public <datatype> ReturnType Methodname(datatype element)
     {
         System.out.println(element);
     }
}
  • “datatype” is only a name. You are free to use “T,” “X,” “Z,” or other identifiers, but there are advisable naming conventions.

Example: Generic Method

public class GenericMethodExample {
   public <T> void printValues(T value) {
       System.out.println("Value : " + value);
   }
   public static <T> void staticdisplayData(T value)
   {
       System.out.println(value);
   }
   public <E> void printArray(E[] elements)
   {
       for ( E element : elements){
           System.out.println(element );
       }
       System.out.println();
   }
}

public class myRunner {
   public static void main(String[] args) {
       System.out.println( "===invoking regular method========" );
       GenericMethodExample obj = new GenericMethodExample();
       obj.printValues(43);
       obj.printValues("Programmer");
       obj.printValues(54.43);
       obj.printValues(true);
       System.out.println( "===invoking static method========" );
       GenericMethodExample.staticdisplayData(254);
       GenericMethodExample.staticdisplayData("Java Developer");
       GenericMethodExample.staticdisplayData(254.25);
       Integer[] intArray = { 10, 20, 30, 40, 50 };
       Character[] charArray = { 'J', 'A', 'V', 'A'};
       System.out.println( "Printing Integer Array" );
       GenericMethodExample.printArray( intArray  );
       System.out.println( "Printing Character Array" );
       GenericMethodExample. printArray( charArray );
   }
}
  • In the above class, we have three generic methods: one generic static method and two generic regular methods. We are going to invoke them in myRunner class.

  • In the above class, the compiler can match the type parameter based on the value passed to the method.

Topic 2b: Generic Type Class

  • A class is generic if it declares one or more type variables. These type variables are known as the type parameters <> of the class.

  • A generic class is implemented exactly like a regular class. The only difference is that it contains a type parameter <> section.

  • There can be more than one type of parameter, separated by a comma. The classes, which accept one or more parameters, are known as parameterized classes or parameterized types.

public class GenericsClass<T1, T2, ... Tn> {...}
  • “T” used inside the angle bracket <> indicates the type parameter.

  • To create objects of a generic class, we use the following syntax:

ClassName <T> obj = new ClassName <T>()
  • “T” is only a name. You are free to use “X” or “Z,” or any other identifier, but these are preferred and advisable naming conventions.

Example: Generic Type Class

Step 1: Create a Generics Class named GenericsClass

public class GenericsClass<T> {
     private T data;  // class variable of T type
   public GenericsClass(T data) { // constructor
       this.data = data;
   }
   // method that return T type variable
   public T getData() {
       return this.data;
   }
}

Step 2: Create a main class named MyRunner

public class MyRunner {
   public static void main(String[] args) {
       // initialize generic class
       // with Integer data
       GenericsClass<Integer> intObj = new GenericsClass<>(5);
       System.out.println("Generic Class returns: " + intObj.getData());
       // initialize generic classa again
       // with String data
       GenericsClass<String> stringObj = new GenericsClass<>("Java");
       System.out.println("Generic Class returns: " + stringObj.getData());
   }
}
  • Here, T used inside the angle bracket <> indicates the type parameter.

  • The getData() method returns exactly the type being held.

  • Notice that within our “GenericsClass” class definition, we use T as if it were a fully-defined type. We do not know exactly what type T is, but we do know that it is a reference type.

  • We also do not know exactly what type the field T is, but since T must be a reference type, we do know that the field T is an Object.

  • “T” is only a name. You are free to use “X” or “Z” or any other identifiers, but there are advisable naming conventions.

Topic 2c: Generic Interface

  • Generics also work with Interfaces.

  • An Interface is generic if it declares one or more type variables. These type variables are known as the type parameters <> of the Interface.

  • Syntax: Declare Generic Interface is as follows:

public interface interface-Name <T> {
.... }
  • Syntax: Implementing a Java generic Interface:

public class class-name implements interface-name<T>
  • For more information about Generic Interfaces, visit the Wiki document.

Example: Generic Interface

Step 1: Create a generic interface named Moveable with type parameter. The interface has a name and a type parameter T. We will declare three abstract methods in interface.

public interface Moveable<T> {
   // abstract method one
   void move(T t, String locationCode);
   // abstract method two
   T getItemBeingMoved();
   // abstract method three
   String getLocationBeingMovedTo();
}

Step 2: Create a generic class named ElephantItem with type parameter. The class definition uses the same type parameters twice – one after the class name and another after the interface name it implements.

public class ElephantItem<U> implements  Moveable<U> {
   private String location;
   private U item;
   @Override
   public void move(U t, String locationCode)
   {
item = t;
       location = locationCode;   }
   @Override
   public U getItemBeingMoved()
   {
       return item;   }
   @Override
   public String getLocationBeingMovedTo()
   {
}
return location;   }

Step 3: Let create a main class named MyRunner:

public class MyRunner {
   public static void main(String[] args) {
ElephantItem<Integer> ObjMove = new ElephantItem<>(); ObjMove.move(5, "NYC");
System.out.println( ObjMove.getItemBeingMoved() + " Item"); System.out.println(ObjMove.getLocationBeingMovedTo() +" Location");
} }
  • Output:

5 Item
NYC Location code

Topic 3: Bounded Types Parameter in Generic

  • Bounded Types Parameter allow us to limit the data type that can be passed through type parameter by using the extends keyword. For example, for any particular generic class, method, or interface that should work only for numeric data types, you can specify using the “extends” keyword.

  • Syntax: <T extends A> Example:

public class GenericsClass <T extends Number> {
// Class body
}
  • The <T extends Number> means that the type parameter of GenericsClass must be a type, which is a subclass of the Number class.

  • We can say that the type parameter is bounded.

Bounded Types Parameter in Generic (continued)

  • A generic type may be declared with multiple type parameters. In addition to simple type parameter names, type parameter declarations can also constrain the set of types allowed by using the extends keyword. Some examples follow:

class Foo<T> {...}
// A class Foo with one type parameter, T.

class Foo<T,S> {...}
// A class Foo with two type parameters, T and S.

class Foo<T extends Number> {...}
// A class Foo with one type parameter T, where T must be instantiated as the type Number or a subtype of Number.

class Foo<T, S extends T> {...}
// A class Foo with two type parameters, T and S. Foo must be instantiated with a type S that is a subtype of the type specified for parameter T.

class Foo<T extends Number & Comparable> {...}
// A class Foo with one type parameter, T. Foo must be instantiated with a type that is a subtype of Number and that implements Comparable.

Example - Bounded Types Parameter in Generic

Sometimes, we do not want to parameterize out classes or methods with just any type, but we want to put some restrictions on them. For instance, suppose we want a box that holds particular kinds of numbers such as a MathBox. What we want to say is that E must be a subtype of Number. Step 1: Create a generic class named MathBox. The class definition uses the type parameters with the keyword, extends, as shown below:

public class MathBox<E extends Number> {
   private E data;
   public MathBox(E data) {
       this.data = data;
   }
     public double sqrt() {
       return Math.sqrt(this.data.doubleValue());
   }
}

Step 2: Let’s create a main class named MyRunner as shown below:

public class MyRunner {
   public static void main(String[] args) {
       // initialize generic class with Integer value
       MathBox<Integer> mObj = new MathBox<Integer>(5);
        // initialize generic class with double value
       MathBox<Double> mObj2 =  new MathBox<Double>(32.1);
       System.out.println(mObj.sqrt());
       System.out.println(mObj2.sqrt());
      //  MathBox mObj3 =  new MathBox<Double>(" Perscholas"); // error
   }
}
  • The following is illegal because String is not a subclass of Number. You will get an Error.

MathBox mBox3 = new MathBox<String>("No good!")

Generic Type Parameter Names

  • The Generic Type Parameter naming convention helps us understand code easily. Having a naming convention is one of the best practices of Java programming language.

  • Unlike variable names, type parameters should be short and capitalized so that they will not be confused with variable or actual type names.

  • Here are some well-advised naming conventions:

    • E

    • K

    • N

    • V

    • T

  • Element (as in an element of a Collection). Key(asinakeyinaMap).

  • Number.

  • Value (as in Key/Value pair).

  • Type (everything else).

  • Note: These are only conventions – the compiler does not enforce them.

As a rule of thumb, you should use:

  • ? extends T if you only need "read" access ("input").

  • ? super T if you need "write" access ("output").

  • T if you need both ("modify").

Topic 4: Generic Wildcard

  • The Wildcard argument is specified by the question mark (?), and it represents an “unknown type.” The extends and super keywords may be used in conjunction with the wildcard to provide upper and lower bounds on the types argument that may satisfy the type constraints.

  • A wildcard is important when creating a generic type that will operate on a class hierarchy.

  • Syntax: In general, to establish an upper bound for a wildcard, use the following type of Wildcard expression: <? extends T> // represents an upper bounded wildcard.

  • Superclass is the name of the class that serves as the upper bound.

  • This is an inclusive clause.

  • You can specify a lower bound for a wildcard by adding a super clause to a wildcard declaration. <? super T> // represents a lower bounded wildcard.

Advantages of Java Generic

  • Code Reusability.

  • Compile-time Type Checking.

  • Used with Java Collections.

Hands-On Lab

Complete the GLAB - 303.11.1 - Generic Method and Class. You can find this lab under Assignment section.

Knowledge Check

  • What is a Generic Type Parameter?

  • How Does a Generic Method differ from a Generic Type?

  • What is a Bounded Types Parameter in Generic?

  • What is Generic Wildcard?

Summary

Java Generic is a language feature that allows for definition and use of generic types and methods. Java Generic is a powerful addition to the Java language because it makes the programmer's job easier and less prone to error. Generic enforces type correctness at compile time, and most importantly, enables implementing.

Learning Objectives:

By the end of lesson, learners will be able to:

  • Describe the Java Collections Interface.

  • Demonstrate how to give implementation of Collection<E> using classes.

  • Describe how to use the Java Collections Framework Generic Classes.

  • Describe the List Interface and implementation of list.

  • Understand the ArrayList<E> Class and Its methods

  • Demonstrate Iterating through ArrayList

  • Utilize the LinkedList<E> Class

  • Declare and Initialize Linkedlist<E>

Last updated