|
The Java Specialists' Newsletter
Issue 140 2007-03-08
Category:
Book Review
Java version: 5+ Book Review: Java Generics and Collectionsby Dr. Heinz M. KabutzAbstract:
Java Generics and Collections is the "companion book" to
The Java Specialists' Newsletter. A well written book that
explains generics really nicely, including some difficult
concepts. In addition, they cover all the new collection
classes up to Java 6 Mustang.
Welcome to the 140th edition of The Java(tm) Specialists' Newsletter, now sent to
113 countries
with the recent addition of Jordan. This morning, my wife
Helene, our baby Evangeline and I went for a lovely walk on
Kalathas Beach, a versatile and wholly pleasant beach, close
to where we live.
The sand is soft, the water shallow (perfect for kids)
but gets deeper after a while (perfect for dad). There is
a rocky outcrop a bit further out, from which you can jump
into the water. There are more fish than at other beaches.
They have a fantastic restaurant on the beach that serves
genuine Cretan cooking. It is a great all-round beach :)
Here are some pictures of Kalathas Beach: http://www.javaspecialists.eu/crete/kalathas.jsp.
Upcoming Java Specialist Master Courses:
- please click here to sign up.
As from May 2010, we are also offering this course on the island of Crete. We
only accept 6 students per class in Crete, due to the size of our conference
room. Please book early to avoid disappointment!
San Jose CA, Mar 16-19 2010, $3500 Ottawa, Canada, Mar 22-25 2010, $3500 Oslo, Norway, Apr 13-16 2010, Kr 24500 Montreal, Canada, Apr 20-23 2010, $3500 Toronto, Canada, May 17-20 2010, $3500 Chania, Crete, May 25-28, Jun 29-Jul 2 or Aug 24-27 2010, €2500
In-house courses if these dates or locations do not suit you - click here for more information.
The companion book to The Java(tm) Specialists' Newsletter!
Occasionally, books are written that appeal to Java
specialists (unfortunately not often enough).
Java Generics and Collections
is such a book. Here are some fascinating nuggets that I
found - there are many more.
Explicit Parameters
Mixing generic methods and varargs produces some
side effects that result in strange syntax, which most
Java programmers don't know. Let's start with the following
class:
import java.util.*;
public class Lists {
public static <T> List<T> toList(T... arr) {
List<T> list = new ArrayList<T>();
for (T t : arr) list.add(t);
return list;
}
}
We can now use this to produce lists of ints or Strings:
List<Integer> ints = Lists.toList(1, 2, 3);
List<String> words = Lists.toList("hello", "world");
At runtime, the arguments are packed into an array, which is
passed to the method toList().
Now comes the catch: What is the generic type that comes back
when you pass different types of objects to the toList()
method, for example:
List<?> something = Lists.toList("one", 2, 3.0);
You would expect that you can simply write:
List<Object> objects = Lists.toList("one", 2, 3.0); // does not compile!
However, this is not possible, since there is a lower common
class, in this case java.io.Serializable.
If you want to bind T to a particular class, for example
Object, you need to use explicit parameters:
List<Object> objects = Lists.<Object>toList("one", 2, 3.0);
You cannot mix explicit parameters with static imports. The
Java grammar requires that type parameters may appear only in
method invocations that use a dotted form.
Although I am certain this appears in other publications,
this book is the first place I read such a clear explanation.
Migrating Legacy Code
In chapter 5: "Evolution, Not Revolution", we see various
approaches we can use when migrating from legacy code to
generics.
Migrating is migrane
and grating rolled into one!
They offer various solutions for legacy and generic clients
and libraries combinations. The most interesting combination
is where you have a legacy library and a generic client.
There are various alternatives:
-
Evolving a library using minimal changes: Change the
method declarations, but keep the actual code the same.
Use a generous helping of
@SuppressWarnings("unchecked) annotations. We
can only do that if we have access to the source.
-
Evolving a library using stubs: Write stubs with generic
signatures but no bodies. We compile the generic client
against the generic signatures, but run the code against
the legacy class files. We can do that when we do not have
access to the source.
-
Evolving a library using wrappers: Here we leave the legacy
source and class files unchanged, and provide a wrapper
class that accesses the legacy class via delegation. This
is actually an anti-pattern and brings with it many
problems. In the book they warn you against its
use.
The book then continues by describing reification and the
effects this has. After that comes reflection with generics.
Both are interesting chapters for Java specialists.
Design Patterns & Generics
In chapter 9, we see several design patterns implemented with
generics, including our popular strategy pattern newsletter,
which is reprinted in the book (with permission). They also
show the Visitor, Interpreter, Function and Observer patterns.
Collections
The book then goes on to Java 5 and Java 6 collections,
including the latest Deque and NavigableMap classes.
Each collection chapter ends with a table of big O notation
for each operations. This is only meant as a guideline in
deciding which implementation to choose. TreeMap can quite
easily outperform HashMap depending on the complexity of the
hashCode(), equals() and compareTo() methods.
Regular and Jumbo EnumSet
One area that the book did not pick up on is the significance
of the EnumSet.noneOf() method. This is
actually a factory method that returns different
implementations of EnumSet depending on the key universe.
If the key universe is larger than 64, it creates a
JumboEnumSet, if it is smaller, a RegularEnumSet.
The JumboEnumSet represents the bitset as a
long[], whereas the RegularEnumSet
simply contains a long.
I suspect that the authors felt this going too deep into
implementation details.
import java.util.EnumSet;
public class EnumSetTest {
public enum SMALL {
A0, A1, A2
}
public enum MEDIUM {
A00, A01, A02, A03, A04, A05, A06, A07, A08, A09,
A10, A11, A12, A13, A14, A15, A16, A17, A18, A19,
A20, A21, A22, A23, A24, A25, A26, A27, A28, A29,
A30, A31, A32, A33, A34, A35, A36, A37, A38, A39,
A40, A41, A42, A43, A44, A45, A46, A47, A48, A49,
A50, A51, A52, A53, A54, A55, A56, A57, A58, A59,
A60, A61, A62, A63
}
public enum LARGE {
A00, A01, A02, A03, A04, A05, A06, A07, A08, A09,
A10, A11, A12, A13, A14, A15, A16, A17, A18, A19,
A20, A21, A22, A23, A24, A25, A26, A27, A28, A29,
A30, A31, A32, A33, A34, A35, A36, A37, A38, A39,
A40, A41, A42, A43, A44, A45, A46, A47, A48, A49,
A50, A51, A52, A53, A54, A55, A56, A57, A58, A59,
A60, A61, A62, A63, A64
}
public static void main(String[] args) {
System.out.println(EnumSet.noneOf(SMALL.class).getClass());
System.out.println(EnumSet.noneOf(MEDIUM.class).getClass());
System.out.println(EnumSet.noneOf(LARGE.class).getClass());
}
}
When we run this, we see as output:
class java.util.RegularEnumSet
class java.util.RegularEnumSet
class java.util.JumboEnumSet
The book has a lot more fascinating information about
generics and collections than I could describe in one
newsletter.
If possible, please consider supporting the authors by
purchasing the book , and not
downloading the PDF from the internet somewhere :-)
Kind regards from Europe
Heinz
P.S. Have you already bought the book? Let
me know if you liked it (or not)!
Book Review Articles
Related Java Course
|