Generic types are extensively used in Java collections. Why do we need Generic types in Java? Understanding this question can help us better understand a lot of related concepts. In this article, I will use a very short example to illustrate why Generic is useful.
1. Overview of Generics
The goal of implementing Generics is finding bugs in compile-time, other than in run-time. Finding bugs in compile-time can save time for debugging java program, because compile-time bugs are much easier to find and fix. Generic types only exist in compile-time. This fact is the most important thing to remember for learning Java Generics.
2. What if there is no Generics?
In the following program, the “Room” class defines a member object. We can pass any object to it, such as String, Integer, etc.
class Room { private Object object; public void add(Object object) { this.object = object; } public Object get() { return object; } } public class Main { public static void main(String[] args) { Room room = new Room(); room.add(60); //room.add("60"); //this will cause a run-time error Integer i = (Integer)room.get(); System.out.println(i); } } |
The program runs totally fine when we add an integer and cast it. But if a user accidentally add a string “60” to it, compiler does not know it is a problem. When the program is run, it will get a ClassCastException.
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer at collection.Main.main(Main.java:21)
You may wonder why not just declare the field type to be Integer instead of Object. If so, then the room is not so much useful because it can only store one type of thing.
3. When generics is used
If generic type is used, the program becomes the following.
class Room<T> { private T t; public void add(T t) { this.t = t; } public T get() { return t; } } public class Main { public static void main(String[] args) { Room<Integer> room = new Room<Integer>(); room.add(60); Integer i = room.get(); System.out.println(i); } } |
Now if someone adds room.add(“60”), a compile-time error will be shown like the following:
We can easily see how this works. In addition, there is no need to cast the result any more from room.get() since compile knows get() will return an Integer.
4. Summary
To sum up, the reasons to use Generics are as follows:
- Stronger type checking at compile time.
- Elimination of explicit cast.
- Enabling better code reusability such as implementation of generic algorithms
Java Generic type is only a compile-time concept. During run-time, all types information is erased, and this is call Type Erasure. Here is an interesting example to show how to avoid the common mistakes of Type Erasure.
References:
1. Why Use Generics?
he not spile, he tru, he correctt .
tank for the correct, I also wonder how add to Object make the run-time.
“Generic types only exist in compile-time. This fact is the most important thing to remember for learning Java Generics.”
Except it is *not* a fact, but a misunderstanding. Generic types *do* exist at runtime, just look at the Java Reflection API (the `java.lang.reflect.Type` interface hierarchy), or look at Java classfiles as rendered by the “javap” command line tool in the JDK.
*Instances* of generic types do not retain the concrete type(s) specified in a `new` expression, sure, but that’s far from saying that “generic types only exist in compile-time”.
Excellent explanation with easy to understand example. Would like to share the same example on question on stackoverflow, will mention this as source as well 🙂
oh,man,you spile hairs。
nice suggestion
as a learner i felt is good
wow man ..you caught it ….nobody would have figure it out ….hats off
The comment is a little misleading:
//room.add(“60”); //this will cause a run-time error
It should be
//room.add(“60”); //the next line would cause a run-time error