The generics feature of Tiger brings greater type safety to Java, allowing developers to do many things they could not do before. Generics bear on a number of other features specific to Tiger. This article introduces you to generics, and what they can do. It is excerpted from chapter two of Java 1.5 Tiger: A Developer's Notebook, written by Brett McLaughlin and David Flanagan (O'Reilly, 2004; ISBN: 0596007388).
Generics of Java 1.5 Tiger - Writing Generic Types (Page 9 of 10 )
With an arsenal of generic terminology under your belt, you’re probably wondering about writing your own generic types. I’m wondering about it, too, so I figure it’s worth covering. They’re actually pretty simple to write, and you’ve already got the tools from earlier labs.
How do I do that?
If you need to define some sort of collection, or container, or other custom object that deals directly with another type, generics add a ton of options to your programming toolkit. For example, Example 2-2 is a basic container structure useful mostly for illustrating important generic concepts.
You can use anything you want for the type parameter, although a single letter is most common.
Example 2-2. A basic generic type
package com.oreilly.tiger.ch02; import java.util.ArrayList; import java.util.List; public class Box<T> { protected List<T> contents; public Box() { contents = new ArrayList<T>(); } public int getSize() return contents.size(); } public boolean isEmpty() { return (contents.size() == 0); } public void add(T o) { contents.add(o); } public T grab() { if (!isEmpty()) { return contents.remove(0); } else return null; } }
Just as you’ve seen in Tiger’s pre-defined generic types, a single letter is used as the representative for a type parameter.
You create a new instance of this type exactly as you might expect:
Box<String> box = new Box<String>();
This effectively replaces all the occurrences of T with String for that specific instance, and suddenly you’ve got yourself a String Box, so to speak.
What about…
…static variables? Static variables are shared between object instances, but parameterization occurs on a per-instance basis. So you could feasibly have a Box<Integer>,a Box<String>, and a Box<List<Float>>, all with a shared static variable. That variable, then, cannot make assumptions about the typing of any particular instance, as they may be different. It also cannot use a parameterized type—so the following is illegal:
private static List<T> staticList = new ArrayList<T>();
You can, however, use static methods that themselves have parameterized types:
public static int biggest(Box<T> box1, Box<U> box2) { int box1Size = box1.getSize(); int box2Size = box2.getSize(); return Math.max(box1Size, box2Size); }