Generic BasicsJ8 Home « Generic Basics
In this lesson we unravel the terminology behind generics and look at some of the the strange syntax we get with it before delving deeper into generics in the following lessons.
Generics were added to the language in Java 5 and were the biggest changes made to the Java language in that release. Although generics are not just for collection types the majority of usage is within collections and so most of the examples in this section will use Collections.
When we talk about generics or a generic type what we are actually talking about is a parameterized type. So a class, interface or method that has has one or more generic types in its definition can be thought of as generic and we can replace the generic type with a parameterized type.
When we define the actual interface, class or method within our code we replace the formal type parameter with the actual type parameter required. As an example we saw in the Collection Hierarchy Diagram that the List interface is specified as List<E>
. The following code shows a declaration of an ArrayList<E>
using a polymorphic declaration that will only except String objects:
package info.java8;
/*
In the following code snippet we replace the formal type parameter E
with an actual type parameter String
*/
List<String> aList = new ArrayList<String>();
<>
(Diamond) Operator Top
The above code is quite verbose and can become difficult to read as shown in the following example which creates a generic map:
package info.java8;
/*
The following code is verbose and hard to read!
*/
Map<String, List<Map<String, Map<String, Integer>>>> map = new HashMap<String, List<Map<String, Map<String, Integer>>>>();
As you can see the above code is quite baffling and so the <>
(diamond) operator was introduced in Java 7 to deal with this.
The <>
operator adds type inference to the right hand side of an assignment when using generics and reduces verbosity.
Following is the above code using the <>
operator:
package info.java8;
/*
The following code uses the <>
operator
*/
Map<String, List<Map<String, Map<String, Integer>>>> map = new HashMap<>();
As you can see the above code uses the <>
operator on the right hand side of an assignment for type inference and is much easier to read!
Generics Overview Top
So what do generics bring to the party? Even pre Java 5 we could create generalized interfaces, classes or methods by using references of the Object
superclass.
So you will see a lot of generalized pre Java 5 stuff that works on Object
but this approach could not guarantee type safety. The problem being that you
need to cast from Object
to the actual type being worked on.
For instance every time you wanted to read from a collection you would need to cast every object you read. If an object of the wrong type was inserted into the collection then the cast could cause a runtime exception. The exception might be in a program completely removed from the collection itself and might not happen for a long time, making every collection a possible ticking timebomb. The exception to this were Array objects where we have always implicitly declared the type on array creation, so arrays have always been type safe.
With generic type declarations of collections the compiler knows that only objects of the specified type can be added to this collection or throws up a compiler error. Through this mechanism we can achieve type safety for our collections and not have to worry about someone else inputting an invalid object into our collections.
Because of the huge impact generics had on the language the developers at Sun microsystems, the original writers of Java and still in control when Java 5 was released, made the decision to keep raw types in the language. For this reason generics are implemented through erasure (all generic code is removed at compile time) so legacy code can interoperate with generic code. This decision was made so that the billions of lines of code already written in Java were still compatible in Java 5. So wherever you see generic code in the language you can, although not in any way recommended, use raw types without any parameterisation instead.
Before we get into some coding now is a good time to look at the various terminology used in the rest of this section:
Generics Terminology Top
Generic terminology can be confusing at first but is fairly easy to understand once you grasp the basics.
When creating your own generic types it is best practice to use pneumonics for the formal type parameter rather than multiple letters.
- E pneumonic for element.
- K pneumonic for key
- T pneumonic for type
- V pneumonic for value
The table below lists various generic examples and the lessons in which each topic is discussed in detail.
Term | Examples | Notes | Lesson |
---|---|---|---|
Raw Type | List | No parameterization. | Raw/Generic Type Comparison |
Generic Type | List<E> | An interface, class or method followed by one or more formal type parameters within angled brackets. | |
Formal Type parameter | E | One or more formal type parameters delimitied by commas, which can be thought of as placeholders for the actual type parameters. | |
Parameterized Type | List<String> | An interface, class or method followed by one or more actual type parameters within angled brackets. | |
Actual Type parameter | String | One or more actual type parameters delimitied by commas. Object types are allowed when using generics but primitive types are not. Array types have always been type safe and so don't require generics. | |
Generic Interfaces | interface SimpleGeneric | An interface followed by one or more formal type parameters delimitied by commas. | Generic Interfaces |
Generic Classes | public class SimpleGeneric | A class followed by one or more formal type parameters delimitied by commas. | Generic Classes |
Bounded Type | <T extends Number> | Create a superclass boundary which all actual type parameters must be, or extend from. | Bounded Type |
Unbounded Wildcard Type | List<?> | Unknown type. | Unbounded Wildcard Type |
Upper Bounded Wildcard Type | List<? extends Number> | Create a superclass boundary which all unknown types must be, or subtypes thereof. | Upper Bounded Wildcard Type |
Lower Bounded Wildcard Type | List<? super Integer> | Create a subclass boundary which all unknown types must be, or supertypes thereof. | Lower Bounded Wildcard Type |
Generic Methods | static <T extends Number> void num(T n) | A method preceded by a generic. | Generic Methods |
Generic Constructors | <T extends Number> CubeNumber(T number) | A constructor preceded by a generic. | Generic Constructors |
Related Quiz
Generics Quiz 1 - Generic Basics Quiz
Lesson 1 Complete
In this lesson we looked at an overview generics and explained certain jargon surrounding generics.
What's Next?
In the next lesson we delve further into generics when we compare raw and generic types.