Making a type-conscious ArrayList
You might not want to give up on this issue just yet. A more ironclad solution is to create a new class using the ArrayList, such that it will accept only your type and produce only your type:
//: c11:MouseList.java
// A type-conscious List.
import java.util.*;
public class MouseList {
private List list = new ArrayList();
public void add(Mouse m) { list.add(m); }
public Mouse get(int index) {
return (Mouse)list.get(index);
}
public int size() { return list.size(); }
} ///:~
Here’s a test for the new container:
//: c11:MouseListTest.java
import com.bruceeckel.simpletest.*;
public class MouseListTest {
private static Test monitor = new Test();
public static void main(String[] args) {
MouseList mice = new MouseList();
for(int i = 0; i < 3; i++)
mice.add(new Mouse(i));
for(int i = 0; i < mice.size(); i++)
MouseTrap.caughtYa(mice.get(i));
monitor.expect(new String[] {
"Mouse: 0",
"Mouse: 1",
"Mouse: 2"
});
}
} ///:~
This is similar to the previous example, except that the new MouseList class has a private member of type ArrayList and methods just like ArrayList. However, it doesn’t accept and produce generic Objects, only Mouse objects.
Note that if MouseList had instead been inherited from ArrayList, the add(Mouse) method would simply overload the existing add(Object), and there would still be no restriction on what type of objects could be added, and you wouldn’t get the desired results. Using composition, the MouseList simply uses the ArrayList, performing some activities before passing the responsibility for the rest of the operation on to the ArrayList.
Because a MouseList will accept only a Mouse, if you say:
mice.add(new Pigeon());
you will get an error message at compile time. This approach, while more tedious from a coding standpoint, will tell you immediately if you’re using a type improperly.
Note that no cast is necessary when using get( ); it’s always a Mouse.
Parameterized types
This kind of problem isn’t isolated. There are numerous cases in which you need to create new types based on other types, and in which it is useful to have specific type information at compile time. This is the concept of a parameterized type. In C++, this is directly supported by the language using templates. It is likely that Java JDK 1.5 will provide generics, the Java version of parameterized types.