Monday, 18 December 2006

SCJP Chapter 7

The last of the big chapters, Chapter 7 deals with collections and generics.

There are four interfaces (Lists, Sets, Maps and Queues) encompassing the eleven classes that implement them (ArrayList, Vector, LinkedList; HashSet, LinkedHashSet, TreeSet; Hashtable, LinkedHashMap, HashMap, TreeMap and PriorityQueue). Basically have to know what methods are available and how they are used, most of which is in the code done for the chapter.

One thing to note is the equals() and hashCode() methods and their contracts. The methods come from the Object class and thus is present in every class afterwards.
The default equals() consider two objects equal if the two references point to the same object, thus to get proper equality of objects (datawise), the equals() need to be overridden with the desired implementation. Otherwise, Sets will allow duplicates in and objects with the default cannot be used as keys in a hashtable. Read the contract (reflexive, symmetric, transitive, consistent and that for any non-null x x.equals(null) will return false) and watch out for questions on this and below.
With equals() overridden, hashCode() must be overridden as well. The default will allow duplicates in a Set. The contract for this one is a bit trickier:
For: x.equals(y) == true
Required: x.hashCode() == y.hashCode()

For: x.hashCode() != y.hashCode()
Required: x.equals(y) == false

For: x.hashCode() == y.hashCode()
Allowed but not required: x.equals(y)

For: x.equals(y) == false
Allowed but not required: No hashCode requirements

Generics enforce compile-time type safety on Collections (and classes and methods declared with generic type parameters). A generic type (eg. Animal) can accept subtypes (eg. Dog, Cat, Wolf). One advantage to type safety is no cast is required when the element type is known. Passing type-safe code into non-type code is dangerous, the compiler will compile it under duress (giving out a warning).

Polymorphism applies to base type, not generic type parameter:
Right: List
aList = new ArrayList();
Wrong: List
aList = new ArrayList();
The generic type must always be the same for declaration and initialization. Another problem is an ArrayList
will not accept any collections of an Animal subtype. This requires further reading.

Wildcard ? allows any type to be assigned, but nothing can be added to the list referred to as List.
With the extends keyword, List ? extends Animal will be able to assign any subtype of List and typed for
or anything that extends Animal (either subclasses or implementations), but still nothing can be added.
With the super keyword, List ? super Animal will be able to assign any subtype of List and typed for
or any supertype of Dog, and allows a restricted way of adding to the collection.

One last thing to note is the use of generic typing in classes and methods, this allows type-checking to be built into the classes and methods, does away with the need to cast and the need to create several subclasses for different types.

No comments: