Beginners Programs :

Generics Class With Multiple Type Parameters In Java

How the generics work with multiple types:

“Generics” mechanism allows us to work with a class (or method) that suits for any type of data. Suppose we want one Stack that holds Integer data and another Stack that holds String data then we need two different classes.

With generics, we can write only one class that works for both the requirements.

Once we write a generic class that class serves for any number of types (not limited to Integer and String).

Suppose we need to develop a class that holds data of a Sports Person and a Politician, another class that holds data of a Politician and a Scientist and yet another class that holds data of a Scientist and a Sports Person.

Then we need to create 3 classes to satisfy the requirements, normally. But with generics, we create only one class that can help to work with any 2 kinds of people. The following example shows such a thing.

Example Program:

Output:

In the above example, we have created a class named Dual at the top. The first line (heading line) of the class is “class Dual<TYPE1, TYPE2>”. This line indicates that the class can work with two different types of data in each of its objects.

So we may create an object of this class like “new Dual<String,Integer>()” so that an object that holds the corresponding (String and Integer) type of data.

If we want to work with a Dual object that needs to work with a Scientist and a SportsPerson objects, then we would create the object as “new Dual<Scientist, SportsPerson>()”. This way we can create each object with a different pair of Types.

  • In the main(), we have created 3 objects (one object for Scientist, one object for Politician and another object for SportsPerson).
  • Then we have created 3 objects of Dual with a different pair of Types each time (the first object with SportsPerson and Politician, the second object with Politician and Scientist and the third object with Scientist and SportsPerson).
  • This indicates that we can create a Dual object with any pair of types. After that, we just have printed each Dual object. each object will print data corresponding to the objects stored in it.

The classes used (Scientist, Politician and SportsPerson) are defined later. Each class has a toString() method to give the data for output.

In C++, the mechanism of “templates” is somewhat similar to the mechanism of “generics” in Java, but they are not the same. We should not jump to any conclusion based on the knowledge of templates in C++.

In C++, a separate class is generated for each type that we specify as type-argument. But in Java, a single class is generated for all the types.

This way we have some differences. As an example, we have a concept (which is different from c++) called bounded-types in Java. The following section briefs it.

Bounded types as parameters in generics

For a generic class, we can send any type as argument. In fact, a generic class is a parameterized (argument) class. It means, it can be used by specifying a type as argument. The class will behave as the specified class-type as a type of the class.

Generally, the Object is at the root of all classes in Java. So, internally Java converts a generic class into a normal class by replacing the type-parameter with Object and performs the required type-castings internally.

For example, if we have a class like the following:

Then, the system converts this class like the following:

With this, the compiler will raise an error that the operator asterisk (*) cannot be applied on wd and ht. because there is no provision in the class Object to perform multiplication on the objects.

As these kinds of operations are generally performed on integers, doubles, etc (numeric type) we should limit the Class usage to numeric types only.

For supporting this kind of situations, we can use the bounded types (limited types/restricted types) concept.

In this bounded types, we specify the class name (which should be used instead of Object while converting a generic class as a normal class before compilation) at the type specification like the following (‘extends’ is used here).

with this, the created class will be upper bounded with Number and the resultant class will be like this.