Generics in Java. “to-be-specified-later”
In this article, we will talk about programming generics and try to understand how they become useful in Java. Rather than giving you set of definitions and making you confused, I think it’s better to concentrate on what problems generics are solving. Once we understand what the problem is and how generic is solving that problem, there will be no question marks in our mind. So first let’s take a look and understand what the actual problem is.
Consider that we have a class that prints variable. So, we create a class called “PrintInteger”, create ‘Integer’ object, and constructor to set the value of ‘val’. And we have a function that prints out ‘val’.
Here, everything seems okay. Let’s now try to do same thing with Double. What we need to do create a new class called “PrintDouble”, copy and paste everything from previous class to new class, change Integer to Double, constructor and so on. To do same thing with Strings, again same processes.
I hope you already felt what the problem is. We are just duplicating our codes, creating new classes, but changing only variable type that we are making operations on. You may agree with me that it increases number of classes without any logic which slow downs the program and decrease the readability.
This is where Generic comes in. In this place, we can create just one class that can take different types of variables. I am creating class “MyClassWithGenerics”. After the class name and before the curly brackets, we put angle brackets and write keyword inside.
public class MyClassWithGenerics <T> { ……}
You can write anything you want inside the brackets as a keyword but usually T is used. You may recognize that we usually put data types or classes inside those brackets. For instance:
ArrayList<String> cars = new ArrayList<String>()
Here, T is a keyword for different objects.
Just like a data type or class, we assign variable to T such as ‘T obj’. And our constructor.
In Main class, we initialize the instance of that class. Inside the angle brackets, we specify what we actually want to pass. For instance, Integer, Double or String. Surprisingly, we pass different types but don’t get any error. Thanks to Generics.
Now, let’s create another method in ‘MyClassWithGenerics’ that prints the type of our ‘obj’ variable using getClass().getName() function. In Main class, we call showType(). Output is here:
Note that you cannot pass primitive data types using generics. For instance, you cannot use ‘int’ instead of ‘Integer’ because int is primitive data type where Integer is a class. Or it will give an error saying, “Type argument cannot be of primitive type”. So, it has to be object, not primitive data type.
Moreover, you can also have more than 1 generic variable. What you need to do is put another keyword with comma in angle brackets, assign variable and add to constructor correspondingly. In our Main class, we will initialize using 2 objects. For example:
As you see we are passing 2 objects as arguments to our object ‘obj1’. One is from java.lang.Integer class and another java.lang.String.
Java generics allow us to utilize code reusability, basically, we don’t need to create a new class for every variable type that we need to use. Now we have the basics of generics. Let’s go ahead and look at something a little bit more advanced.
I am creating a new class called ‘NumericOps’. Also, I implement function double square() which returns obj * obj.
As you can see here, we’re trying to multiply object with object. Naturally, we’re getting this error here that says, “T extends Object”. So, if we have numeric objects such as Integer or Double, it is quite okay to multiple. What if we have String? What does “T extends Object” means? How to ensure that T always be numeric object?
What generics provide is something called bounded types where you can bound the type of your generic to special classes. In default, T extends Object class which means T can be any type of object. So let’s switch from default to custom.
In this piece of code, T extends Number means that we bound T to be type of Number class, which is superclass of Integer, Double, Float and etc. However, as a default it extends Object class which is superclass of all types. As you can see, no errors occur in this case. Let’s run this code.
It works fine! If we have String instead of Integer, it will give error saying that “Type parameter is not from bound”.
It is worth to mention that generic keyword can be question mark. <?> is a shorthand for <? extends Object>, it’s also known as an unbounded wildcard. So, you can specify any type of object in your generic. For example, the List class is declared as List<?>, because it can be a list of anything you want.
In this article, I tried to explain programming term “Generics” through code of examples written in Java. For the person who faces with generics for the first time, those ‘T’s, ‘?’s can be confusing, however, generics is super easy and useful for both writer and reader.