Why Generics in Java?
Generics got introduced in Java SE 5.0, but the question is why use generics in the first place?
In this tutorial, we are going to look at some of the problems that developers faced before generics.
Before generics, it is the developer’s responsibility to add the correct types of elements to the list. Also, it is the developer’s responsibility to cast the element to the correct type.
Problems before generics
- Our intention is to store String names on the list
- A list without a generic type can hold any type of object reference i.e String, Car, Student, etc
- While getting the elements back from the list, the list returns Object. So the cast to String is necessary
- Also, if the stored object is not of the String type then that will result in an error during casting
Let’s look at a program that demonstrates all of the above points.
Program without generics
import java.util.ArrayList; import java.util.List; // This program shows // how things worked before generics public class WithoutGenerics { public static void main(String[] args) { // Create an instance of ArrayList // without generics // the intention is to store String names List names = new ArrayList<>(); // Add String elements names.add("Adam"); names.add("Chris"); names.add("James"); // Add int element // This works fine without generics names.add(10); // Print the elements System.out.println("Elements : " + names); // Fetch the String element and print String thirdName = (String) names.get(2); System.out.println("Element at position 3 : " + thirdName); // Fetch the String element // But the element turns out to be an int // This cast from int to String will // result in an error String invalidName = (String) names.get(3); System.out.println("Element at position 3 : " + invalidName); } }
Output
Elements : [Adam, Chris, James, 10] Element at position 3 : James Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String at WithoutGenerics.main(WithoutGenerics.java:34)
Explanation
- Create an instance of ArrayList without Generics. This means the instance of List can hold any type of Object. But our intention is to store String names to it
- Add names Adam, Chris, and James to it. Till this point things are fine
- Now, add 10 to the list. Adding 10 is not a problem as the List can accept any Object type
- When you try to fetch “James” and cast it to String, things are fine
- But as we have also added 10 to the List, So casting it to String will cause the ClassCasteException
- This is the problem that generics is trying to solve
To solve this problem Java community introduced Generics in Java SE 5.0.
Now we will look at how things become simpler with generics.
Program with Generics
import java.util.ArrayList; import java.util.List; // This program shows // how things work with generics public class WithGenerics { public static void main(String[] args) { // Create an instance of ArrayList // of type String // the intention is to store String names Listnames = new ArrayList<>(); // Add String elements // It is fine to add String elements names.add("Adam"); names.add("Chris"); names.add("James"); // Try to add int element // This is a compiler error names.add(10); // Print the elements System.out.println("Elements : " + names); } }
Explanation
- Our intention is to store String names on the list
- Create a list with String generic type
- Generics is a compile-time feature. So, the compiler makes sure you can only add String elements
- Try to add 10 to the list and that results in a compiler error
Conclusion
- We saw without generics developers have to add the right types of elements to the list
- Also, without Generics developers have to cast the element to the right type after getting it back
- After generics, it is the compiler’s responsibility to make sure that the right types of elements get added to the list
- Finally, casting is not required while getting the elements back