Java
November 12, 2020

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.