Become a fan of Slashdot on Facebook

 



Forgot your password?
typodupeerror
×
Book Reviews Books Media

Java Generics and Collections 278

andrew cooke writes "Java 6 was recently released, but many programmers are still exploring the features introduced in Java 5 — probably the most significant changes in the language's twelve year history. Amongst those changes (enumerations, auto-boxing, foreach, varargs) generics was the most far-reaching, introducing generic programming in a simpler, safer way than C++ templates and, unlike generics in C#, maintaining backwards (and forwards) compatibility with existing Java code." Read on for the rest of Andrew's review.
Java Generics and Collections
author Maurice Naftalin, Philip Wadler
pages 273
publisher O'Reilly Media, Inc.
rating 9/10
reviewer Andrew Cooke
ISBN 978-0-596-52775-4
summary Guide to Java generics; also includes interesting discussion of collection classes.


Given the history of Generic Java, Naftalin and Wadler's Java Generics and Collections has a distinguished pedigree. In this review I'll argue that this is a new classic.

If you're a Java programmer you've probably heard of generics, an extension to the type system that was introduced in Java 5. They give you, as a programmer, a way to write code even when you don't know exactly what classes will be used.

The obvious example is collections — the author of a List class has no idea what type of objects will be stored when the code is used.

Before generics, if you wanted to write code that handled unknown classes you had to use make use of inheritance: write the code as if it would get Objects, and then let the caller cast the result as necessary. Since casts happen at runtime any mistakes may cause a runtime error (a ClassCastException).

Generics fix this. They let you write code in which the classes are named (parameters) and the compiler can then check that the use of these class parameters is consistent in your program. So if you have a List of Foo instances you write List<Foo> and the compiler knows that when you read that list you will receive a Foo, not an Object.

I'll get to the book in a moment, but first a little history. If you know any type theory — particularly as used in functional languages like ML and Haskell — then you'll recognize my quick description above as parametric polymorphism. You'll also know that it is incredibly useful, and wonder how Java programmers could ever have managed without it.

Which explains why Philip Wadler, one of the people responsible for Haskell, was part of a team that wrote GJ (Generic Java), one of the experimental Java mutations (others included PolyJ and Pizza) that, back in the day (late 90s) helped explore how parametric polymorphism could be added to Java, and which formed the basis for the generics introduced in Java 5.

So if you want to understand generics, Wadler is your man. Which, in turn, explains why I jumped at the chance to review O'Reilly's Java Generics and Collections, by Maurice Naftalin and Philip Wadler.

This is a moderately slim book (just under 300 pages). It looks like any other O'Reilly work — the animal is an Alligator this time. It's well organized, easy to read, and has a decent index.

There's an odd discrepancy, though: Wadler is the generics Guru; this is going to be `the generics reference'; generics are sexy (in relative terms — we're talking Java here) and collections are not; the title has "Java Generics" in great big letters with "and Collections" in little tiny ones down in a corner. Yet very nearly half this book is dedicated to collections.

Generics is a great, practical read. It starts simply, introducing a range of new features in Java 5, and then builds rapidly.

If you are completely new to generics, you'll want to read slowly. Everything is here, and it's very clear and friendly, but there are not the chapters of simple, repeated examples you might find in a fatter book. Within just 30 pages you meet pretty much all of generics, including wildcards and constraints.

If that makes your head spin, don't worry. Read on. The next hundred or so pages don't introduce any new syntax, but instead discuss a wide range of related issues. The chapters on Comparisons and Bounds and Declarations contain more examples that will help clarify what generics do. And the following chapters on Evolution, Reification, and Reflection will explain exactly why.

So the first seven chapters introduce generics and then justify the implementation — any programmer that takes the time to understand this will have a very solid base in generics.

There are even some interesting ideas on how Java could have evolved differently — section 6.9 Arrays as a Deprecated Type presents a strong case for removing arrays from the language. It's a tribute to the clarity and depth of this book that the reader is able to follow detailed arguments about language design. Fascinating stuff.

The next two chapters, however, were my favorites. Effective Generics and Design Patterns give sensible, practical advice on using generics in your work, including the best explanation of <X extends Foo<X>> I've seen yet (so if you don't know what I am talking about here, read the book).

(A practical word of advice — if at all possible, use Java 6 with generics. Java 5 has a sneaky bug).

The Collections part of the book was more along O'Reilly's `Nutshell' lines: the different chapters explore different collection types in detail. I must admit that at first I skipped this — it looked like API docs re-hashed to extend the size of the book.

Then I felt bad, because I was supposed to be reviewing this book (full disclosure: if you review a book for Slashdot you get to keep it). And you know what? It turned out to be pretty interesting. I've programmed in Java for (too many) years, and I guess I've not been quite as dedicated to tracking how the library has changed as I should have been — I learned a lot.

Again, a wide range of readers are welcome. This is more than a summary of the Javadocs, ranging from thumbnail sketches of trees and hashtables to a discussion of containers intended for multi-threaded programming.

The way I see it now, this part is a bonus: the first half, on generics, makes this book one of the standards; the second half is an extra treat I'm glad I stumbled across (I guess if you're some kind of weird collection-fetishist maybe it's even worth buying the book for).

I've used generics since the first beta release of Java 5 and had experience with parametric polymorphism in functional languages before that (in other words, I can tell my co- from my contra-variance). So I guess I'm heading towards the more expert end of the spectrum and I was worried I'd find the book boring. It wasn't. After claiming to be expert I don't want to spoil things with evidence that I'm actually stupid, but reading this book cleared up a few `misunderstandings' I'd had. I wish I had read it earlier.

If you're new to generics, and you don't mind thinking, I recommend this book. If you're a Java programmer who's a bit confused by <? super Foo> then this is the book for you.

The only people who shouldn't read this are people new to Java. You need to go elsewhere first. This is not a book for complete beginners. This is a great book in the classic — practical, concise and intelligent — O'Reilly mould.


You can purchase Java Generics and Collections from amazon.com. Slashdot welcomes readers' book reviews -- to see your own review here, read the book review guidelines, then visit the submission page.
This discussion has been archived. No new comments can be posted.

Java Generics and Collections

Comments Filter:
  • by e2d2 ( 115622 ) on Monday April 16, 2007 @02:32PM (#18753565)
    Uhm, can someone explain to me how NEW features of a language can be backwards compatible?

    Can I create generics in Java 1.1? If not then how exactly is their generics implementation backwards compatible? Call me crazy but I'm a bit skeptical. I just don't see how this can be done in ANY language. Just because you can run multiple versions of the runtime on the same machine doesn't mean that your new code is backwards compatible.

  • by JebusIsLord ( 566856 ) on Monday April 16, 2007 @02:39PM (#18753693)
    Man, that is just not fair. Microsoft has been burdened with backwards compatibility like no other company out there. I mean, except on 64-bit Vista, you can still run 16-bit DOS apps in the latest release of Windows, 20+ years later! Try running a circa 2001 OS9 app on a new Mac, and let me know how that goes for you. Microsoft has been hamstrung by their commitment to backwards compatibility; I am convinced that (and bad management) are the reasons for Vista's mediocrity. Yeah, some stuff broke, but I wish they'd broken more in the pursuit of a "good" OS.

    On topic, C# 2.0 was introduced with .NET 2.0, which included bytecode optimizations that aren't backwards-compatible. The generics stuff probably could have been, but meh; Microsoft controls the only real .NET platform anyhow. Its not like they had to remain compatible with mobile phones and such, like Sun did.
  • by Cyberax ( 705495 ) on Monday April 16, 2007 @02:46PM (#18753787)
    Bullshit.

    Generics syntax is quite readable and easy-to-use, especially with good IDE support. And generics certainly make the code more readable because the add type information.

    Foreach loops, varargs and autoboxing is just a minor syntax sugar, nothing really big.

    I've used a lot of collection frameworks in a lot of languages (and even wrote my very own vector and string for C++), Java Collections Framework is quite OK. It's not hard and reasonably fast.
  • by Hikaru79 ( 832891 ) on Monday April 16, 2007 @02:49PM (#18753835) Homepage
    Who ever saw a version of a Microsoft product that was compatible with the previous version?

    Are you joking? I hope you're joking. Because the alternative is that you are being criminally thick. I really think Slashdot should have a mod option -1 Misinformed

    Say what you will about Microsoft, but backwards compatibility has always been one of their cornerstones. Their compatiblity layers still allow you to run apps from the early 90's on a modern copy of Vista today. I have managed to get some very old VB3 code working with a minimum of modification on VB6, which then, using Project Analyzer, got compiling in .NET in a matter of (admittedly frustrating) days.

    And who are you comparing them with? Linux? You must be joking. Linux has trouble (read: is completely unable to) maintain binary compatibility with even relatively recent "old" code because of changing libc versions, etc.

    Please, name ONE other operating system out there that can claim to run decade-old binaries flawlessly in its most recent incarnation.

    Disclaimer: I'm a dedicated FOSS user and not a Microsoft shill in any way. But please, let's give credit where credit is due.
  • by mr_mischief ( 456295 ) on Monday April 16, 2007 @02:56PM (#18753951) Journal
    Wouldn't someone have to be used to _only_ Java to not be familiar with at least some of these concepts?

    Enumerations are available in Pascal and pretty much all of its descendants IIRC. It's also a type of field in an SQL database for much the same purpose as enumerations in programming languages.

    The foreach loop has been in Perl since 2.0 in 1988. C# got foreach in 2000. It's in PHP. It comes from earlier FOR..IN loops from shells.

    I'm sure there are examples of the other features which are similar to the Java version of them. The syntax may be different, and the exact details of darker semantic corners may be different. The concepts, however, are pretty easy to have run across unless someone has only used the one language.

    The review seems to imply that bringing in what has been proven to work well in other languages is too confusing and should be done at a slower pace. The truth is, people program in a subset of any general-purpose language at first, and that subset grows over time. If someone works with code from other programmers, one picks up the parts of the language to which they are exposed as they are exposed to them. No one needs to cram all night to be up on all the new features of a language the day after the manual gets updated.
  • by LarsWestergren ( 9033 ) on Monday April 16, 2007 @03:27PM (#18754409) Homepage Journal
    The only thing it offers is some compile-time sanity checking, but even that can be disabled through use of a new compiler pragma directive to suppress warnings.

    Many operations are ERRORS, not warnings. This is caught by IDEs, and by the compiler.

    In order to make it possible to interact with legacy code, you can pass a generified collection to a method that expects a "raw" collection. This gives you a very clear warning. So for 95% of all use cases, generics give you a lot of assistance. You manage to come up with a remaining 5% example, where a programmer casts, suppresses compiler warnings, and then passes in a object of the wrong type, and this makes generics worthless?

    Wadler was involved with the design of Haskell, and he and people like Gilad Bracha designed Java generics. I trust their skills more than a Slashdot Anonymous Coward.
  • by DavidYaw ( 447706 ) on Monday April 16, 2007 @04:18PM (#18755051) Homepage

    Ever wondered why the collection classes require you to pass in an array to the toArray(T[]) method? Because Java generics throw away the class information after compile time (although there's no reason they need to do this, they could have kept it and maintained backwards compatibility), so you have to pass in an array to give the type information Java removed.


    A) Before generics were added, the toArray(T[]) function already existed as toArray(Object[]). Since this function pre-dates generics, the fact that it takes an array parameter, by definition, cannot have anything to do with generics.

    B) For the interface Collection<E>, the function is defined as toArray(T[]), not toArray(E[]). The generic type T is defined locally for this function, and it does not have to be the same as type E.

    I believe that in the quote, you are suggesting that this function should be implemented as taking no parameters and returning an array of the same type as the enumerated type. While I agree that this would be useful, it does not give as much functionality as toArray(T[]), and is not a suitable replacement.
  • by Anonymous Brave Guy ( 457657 ) on Monday April 16, 2007 @04:25PM (#18755177)

    It means that you can create List and pass it to a legacy method which takes only unparameterized List.

    Whether that is a useful compatibility mechanism or a fundamental weakness in the type system that defeats the entire point of generics is left as an exercise to the reader.

"Experience has proved that some people indeed know everything." -- Russell Baker

Working...