Tuesday, January 16, 2018

"Effective Java" book outline

Effective Java was written by Joshua Bloch in 2001, and the second edition released in 2009 shortly after the release of Java 6.  I received a copy of the second edition from my manager as recommended reading.  While it was sometimes a little dated, it still made for easy reading, and it felt like most of the recommendations would still be pretty relevant.  As it happens, there is now a third edition that covers Java 7, 8, and 9 which may be worth checking out...

Overall I was impressed with the advice given in the book.  In order to make better practical use of it, I wanted to create a basic "outline" view that I could easily find and scan, making reference back to the book if needed.  That is really all this post is.  I thought about adding "notes"... either to each item or to each section, but they just cluttered it up.  I want this to be more a quick cheat sheet of the guidelines, not a full blown Readers Digest edition of the book...



  1. Consider static factory methods instead of constructors
  2. Consider a builder when faced with many constructor parameters
  3. Enforce the singleton property with a private constructor or an enum type
  4. Enforce noninstantiability with a private constructor
  5. Avoid creating unnecessary objects
  6. Eliminate obsolete object references
  7. Avoid finalizers
  8. Obey the general contract when overriding equals 
  9. Always override hashCode when you override equals
  10. Always override toString
  11. Override clone judiciously
  12. Consider implementing Comparable
  13. Minimize the accessibility of classes and members
  14. In public classes, use accessor methods, not public fields
  15. Minimize mutability
  16. Favor composition over inheritance
  17. Design and document for inheritance or else prohibit it
  18. Prefer interfaces to abstract classes
  19. Use interfaces only to define types
  20. Prefer class hierarchies to tagged classes
  21. Use function objects to represent strategies
  22. Favor static member classes over nonstatic
  23. Don't use raw types in new code
  24. Eliminate unchecked warnings
  25. Prefer lists to arrays
  26. Favor generic types
  27. Favor generic methods
  28. Use bounded wildcards to increase API flexibility
  29. Consider typesafe heterogeneous containers
  30. Use enums instead of int constants
  31. Use instance fields instead of ordinals
  32. Use EnumSet instead of bit fields
  33. Use EnumMap instead of ordinal indexing
  34. Emulate extensible enums with interfaces
  35. Prefer annotations to naming patterns
  36. Consistently use the Override annotation
  37. Use marker interfaces to define types
  38. Check parameters for validity
  39. Make defensive copies when needed
  40. Design method signatures carefully
  41. Use overloading judiciously
  42. Use varargs judiciously
  43. Return empty arrays or collections, not nulls
  44. Write doc comments for all exposed API elements
  45. Minimize the scope of local variables
  46. Prefer for-each loops to traditional for loops
  47. Know and use the libraries
  48. Avoid float and double if exact answers are required
  49. Prefer primitive types to boxed primitives
  50. Avoid strings where other types are more appropriate
  51. Beware the performance of string concatenation
  52. Refer to objects by their interfaces
  53. Prefer interfaces to reflection
  54. Use native methods judiciously
  55. Optimize judiciously
  56. Adhere to generally accepted naming conventions
  57. Use exceptions only for exceptional conditions
  58. Use checked exceptions for recoverable conditions and runtime exceptions for programming errors
  59. Avoid unnecessary use of checked exceptions
  60. Favor the use of standard exceptions
  61. Throw exceptions appropriate to the abstraction
  62. Document all exceptions thrown by each method
  63. Include failure capture information in detail message
  64. Strive for failure atomicity
  65. Don't ignore exceptions
  66. Synchronize access to shared mutable data
  67. Avoid excessive synchronization
  68. Prefer executors and tasks to threads
  69. Prefer concurrency utilities to wait and notify
  70. Document thread safety
  71. Use lazy initialization judiciously
  72. Don't depend on the thread scheduler
  73. Avoid thread groups
  74. Implement Serializable judiciously
  75. Consider using a custom serialized form
  76. Write readObject methods defensively
  77. For instance control, prefer enum types to readResolve
  78. Consider serialization proxies instead of serialized instances


Additions in the third edition, with the section in blue representing an entirely new category of items related to Streams and Lambdas, which were introduced in Java 8:
  • Prefer dependency injection to hard wiring resources
  • Avoid cleaners
  • Prefer try-with-resources to try-finally
  • Design interfaces for posterity (aka Avoid default methods on interfaces)
  • Limit source files to a single top-level class
  • Combine generics and varargs judiciously
  • Prefer lambdas to anonymous classes
  • Prefer method references to lambdas
  • Favor the use of standard functional interfaces
  • User streams judiciously
  • Prefer site-effect-free functions in streams
  • Prefer Collection to Stream as a return type
  • Use caution when making streams parallel
  • Return optionals judiciously
  • Prefer alternatives to Java serializations

Josh Bloch gives a talk on the second edition which is well worth a watch: 




No comments:

Post a Comment