Effective Java, Third Edition

I can finally review the long- anticipated third edition of the classic book Effective Java, by Joshua Bloch. Its release at the end of 2017 brought the book’s content up to date with Java 9. Given that the previous edition covered only through Java 6, you can see how long this edition has been anticipated by Effective Java’s many fans—fans who justifiably appreciate the clear and elegant execution of the book’s central promise: a discussion of best practices in Java programming. Bloch presents these practices through a series of 90 short essays (up from 78 in the previous edition), each of which elaborates a useful recommendation. For example, here are some of the best practices added in this volume:

  • Prefer method references to lambdas
  • Prefer Collection to Stream as a return type
  • Use Streams judiciously

As you can see, these recommendations are true best practices. That is, they are not intended as tutorials on the language, but rather as good things to do once you’ve learned the language and are using it daily. The first example on the list above will likely elicit from some readers a “Huh, I never thought about that” response. And that is precisely what gained this book praise and attention in its original release—the many recommendations that readers simply had not considered, or if they’d considered them, had not explored fully.

Other recommendations such as “Use Streams judiciously” seem banal in their formulation. “Use x judiciously” is always good advice, so what makes this suggestion important? Bloch’s eight-page explanation details how Streams should be used. His principal thesis is that Streams provide little benefit if they don’t implement a functional-style operation. To facilitate this, Bloch dives into the Collectors API and explains its tight relationship with operations for which many developers misuse Streams. The explanation contains examples of badly used Streams and the correct use. In the process, you learn a lot about how Streams and Collectors operate, the intended use of Streams, and how to apply that knowledge to write better and clearer code. Not bad for eight pages!

The recommendations stretch across many topics, from tricky topics such as the Serializable interface, to the more mundane, such as when to omit accessors on data-only classes.

The book is supremely readable: the style is concise and clear, and the code examples are short and to the point. As a result, Effective Java is a pleasant volume to read through from beginning to end—learning to refine your coding skills as you go. It is one of the very few books I recommend without reservation to all Java programmers who are past the beginner stage.