Java Reference
In-Depth Information
public static void main(String[] args) {
LinkedList<GenericRole<String, String>> roleMap =
new LinkedList<GenericRole<>>();
roleMap.add(new GenericRole<String, String>("Humphrey Bogart",
"Sam Spade"));
System.out.println(roleMap.getFirst().getActor() +
" appeared on screen as " + roleMap.getFirst().getRole());
}
}
Notice that we now have parameters nested within parameters (in
LinkedList<GenericRole<String, String>> roleMap ). When a parameterized (that is, generic) collection
consists of a type of object that itself has parameters, you get nested generic specifiers. It may seem odd,
but it's common practice once you start using generics.
You can also specify that a collection can contain multiple kinds of objects, provided that the
objects all extend the same class or implement the same interface. To do so, Java includes a wildcard (in
the form of the question mark character) that you can use with generic specifiers. For an example,
consider Listing 15-5.
Listing 15-5. Using the Generic Wildcard
LinkedList<? extends JPanel> panels = new LinkedList<>();
That declaration says any class that extends JPanel can be a member of this list. Remember all the
times I extended JPanel in the chapters about animation, video games, and recursion? If I ever need a
single list to hold those different panels, the list above would do the job nicely.
The extends keyword works with interfaces, too. So, if I wanted a list of classes that implement the
MouseListener interface, I could use the declaration shown in Listing 15-6.
Listing 15-6. A Generic for an Interface
LinkedList<? extends MouseListener> mouseListeners = new LinkedList<>();
Listing 15-7. A Generic with the Super Keyword
LinkedList<? super JPanel> panelAncestors = new LinkedList<>();
The super keyword specifies that any object extended by the JPanel class can be a member of this
list. For this list, that would be objects of type javax.swing.JComponent . The super keyword is probably
most useful when you want to ensure that the objects that satisfy a parameter are comparable (so that
they can be sorted). In my experience, it's not often used, so I won't dive into it any further.
Now that we've seen the syntax for generics, let's talk about why you want to use them. The biggest
benefit is earlier error detection. It's a truism in software development (and many other professions) that
the earlier you catch an error, the less expensive it is to fix. If we can catch an error at coding time, fixing
it is just a matter of re-writing code we're already working on; the cost is trivial. If an error makes it to the
testers (assuming we have testers—not all software companies have test teams), it's more expensive. The
test team has to find it and tell the developer about it, the developer (who has moved on to some other
task) has to re-open and modify that code, and then the test team has to verify that the fixed code works
correctly. The worst result is when an error gets all the way to the customer; we get all the added expense
of communicating with the test team and the customer, with the added (and usually more important)
Search WWH ::




Custom Search