Theory: Generics and Object
As you know, generics enable types to be parameters when defining classes (or interfaces) and methods. Parameterized types make it possible to re-use the same code while processing different concrete types.
Reusing code with generics
Let's consider a generic class named GenericType
that stores a value of "some type".
It is possible to create an object with a concrete type (e.g., String
):
You can also create instances with other types (Integer
, Character
) and then invoke the get
method to take the internal field. So, generics allow you to use the same class and methods for processing different types.
Reusing code with Object
But there is another way to reuse code. If we declare the class field as Object
, we can assign a value of any reference type to it. This approach has been widely used before Java 5.
The class NonGenericClass
demonstrates it.
Now we can create an instance of this type with the same string as in the previous example (see GenericType
).
It is also possible to create an instance passing a value of type Integer
or Character
.
That is how you can reuse the same class with an Object
field to store different types in the same way.
The advantage of generics: from run-time to compile-time
After an invocation of the method get()
we obtain an Object
, not a String
or an Integer
. We cannot get a string directly from the method.
To get the string back, we should perform an explicit type-casting to the String
class.
Of course, it works, but what if the instance does not store a string at all? Since it is declared as an Object
, the field value can keep any type. If this is the case, the code throws an exception. Here is an example:
Now we can see the main advantage of generics over the class Object
to re-use code. There is no need to perform an explicit type-casting and, as a consequence, we never get the runtime exception. If we do something wrong, we can see it at the compile-time.
A compile-time error is detected by the programmer, not a user of the program. This makes generics both flexible and safe. At the same time, working with Object
that requires type-casting is error-prone. It's better to let the compiler take care of it.
Generics without specifying a type argument
When you create an instance of a generic class, you have a possibility not to specify an argument type at all.
In this case, the field of the class is Object
, and the method get returns an Object
as well.
It is the same as the following line:
Usually, you will not use generics parameterized by Object
because it has the same problems as presented above. Just remember that this possibility exists.
Conclusion
Both generics and Object allows you to write a generalized code. Using Object
, however, may need explicit type-casting that is error-prone. Generics provide type-safety by shifting more type checking responsibilities to the Java compiler.