Effective Java: 51 Essential Practices for Writing Clean, Efficient Java Code
This article distills key recommendations from Effective Java, covering static factory methods, builder patterns, singleton safety, utility class design, object creation, memory management, garbage‑collection, equals/hashCode contracts, immutability, generics, enums, collections, exception handling, and performance‑aware coding practices for robust Java development.
Effective Java is a classic guide for Java developers; adhering to its principles dramatically improves API quality and overall code craftsmanship.
1. Prefer static factory methods over constructors
Examples such as Integer.valueOf("1") and Boolean.valueOf("true") provide better readability, potential performance gains, and higher flexibility.
Advantages
Readable method names
Can avoid object creation
More flexible (can return subclasses)
Readability
Methods like Point.at(x, y) convey intent better than new Point(x, y) .
Performance
Static factories can return cached instances, e.g., Boolean.TRUE and Boolean.FALSE .
public final class Boolean implements Serializable, Comparable<Boolean> {
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
...
public static Boolean valueOf(boolean b) { return b ? TRUE : FALSE; }
public static Boolean valueOf(String s) { return parseBoolean(s) ? TRUE : FALSE; }
}Flexibility
Factories can return subclasses, as shown by Collections.emptyList() .
public class Collections {
private Collections() {}
public static final List EMPTY_LIST = new EmptyList<>();
public static
List
emptyList() { return (List
) EMPTY_LIST; }
...
}2. Use builders when a class has many constructors
Multiple constructors can become unwieldy, especially in Android UI components. A builder centralizes parameter validation and improves readability.
public class AlertDialog {
private AlertDialog(Builder b) { /* validate */ }
public static class Builder {
private int width;
private int height;
private String title;
public Builder setTitle(String t) { this.title = t; return this; }
...
public AlertDialog build() { return new AlertDialog(this); }
}
}3. Strengthen singletons with private constructors or enums
Private constructors prevent reflection attacks; enums guarantee a single instance even after serialization.
public class Elvis {
public static final Elvis INSTANCE = new Elvis();
private Elvis() {}
} public enum Elvis { INSTANCE; }4. Make utility classes non‑instantiable
Declare a private constructor that throws an exception to avoid accidental instantiation.
public class Util {
private Util() { throw new AssertionError(); }
}5. Avoid creating unnecessary objects
Reuse objects when possible
Use object pools for expensive resources
Do not pool cheap objects; modern JVMs handle them efficiently
6. Eliminate obsolete object references
Three common memory‑leak sources: self‑managed memory (e.g., shrinking arrays), caches, and listeners/callbacks. Null out references after use.
public Object pop() {
if (size == 0) throw new EmptyStackException();
elements[size] = null; // help GC
return element[--size];
}7. Do not invoke garbage collection explicitly
Rely on the JVM’s automatic GC; explicit finalizer calls are costly and often unnecessary.
8‑10. Follow the equals/hashCode/toString contract
Reflexive, symmetric, transitive, consistent, non‑null
Always override hashCode when equals is overridden
Provide a meaningful toString implementation
11‑13. Use clone cautiously, implement Comparable when natural ordering makes sense, and minimize member accessibility
Prefer private > protected > package‑private > public to reduce coupling.
14‑18. Prefer interfaces over public fields, use enums instead of int constants, and favor composition over inheritance
Composition (wrapper/decorator) reduces fragile inheritance hierarchies.
19‑23. Use generics, bounded wildcards (PECS), and avoid raw types
public void pushAll(Iterator
src) { for (E e : src) push(e); }
public void popAll(Collection
dst) { while (!isEmpty()) dst.add(pop()); }24‑30. Prefer EnumSet/EnumMap over bit‑mask flags, avoid string‑based type representations, and use appropriate numeric types
public enum Style { BOLD, ITALIC, UNDERLINE, STRIKETHROUGH }
public void applyStyles(SetTop Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.