Mastering Java Essentials: Builders, Immutability, and Best‑Practice Patterns
This article distills key concepts from Effective Java—covering object creation with Builder pattern, preventing unwanted instantiation, minimizing mutability, thoughtful class and interface design, generics nuances, method signatures, handling nulls with Optional, and disciplined exception documentation—providing actionable code examples for robust Java development.
1. Object Creation and Destruction
When a class has many constructor parameters, avoid the JavaBeans pattern with a no‑arg constructor and setters; instead, prefer the Builder pattern to create immutable objects. Lombok’s @Builder can generate the builder automatically.
import lombok.Builder;
/** Request class */
@Builder
public class SampleRequest {
private String paramOne;
private int paramTwo;
private boolean paramThree;
}
/** Response class */
@Builder
public class SampleResponse {
private boolean success;
}
/** Service interface */
public interface SampleFacade {
Result<SampleResponse> rpcOne(RequestParam<SampleRequest>);
}
public void testRpcOne() {
SampleRequest request = SampleRequest.builder()
.paramOne("one").paramTwo(2).paramThree(true).build();
Result<SampleResponse> response = sampleFacade.rpcOne(request);
}2. Classes and Interfaces
Minimize visibility of classes and members; use package‑private or Guava’s @VisibleForTesting for test‑only access. Private constructors prevent instantiation of utility classes.
public class SampleUtility {
public static String getXXX() { return "test"; }
/** Private constructor */
private SampleUtility() {}
}
public static void main(String[] args) {
System.out.println(SampleUtility.getXXX());
}3. Generics
Prefer lists over arrays; arrays are covariant and checked at runtime, while generics are invariant and type‑checked at compile time. Avoid exposing public static final arrays as they can become security risks.
4. Methods
Validate method parameters early and throw appropriate exceptions. Design method signatures carefully: use verb‑based names, prefix boolean methods with is, keep parameter lists short (ideally ≤4), and consider auxiliary holder classes for many arguments.
public class SampleListener {
public ConsumeConcurrentlyStatus consumeMessage(String input) {
SampleResult result = generateResult(input);
// ...
}
private static SampleResult generateResult(String input) { /* ... */ }
private static class SampleResult {
private boolean success;
private List<String> xxxList;
private int count;
}
}Return empty collections instead of null; use Optional to express possible absence of a value.
/** Recommended */
public Optional<Foo> findFoo(String id);
/** Not recommended: defeats Optional purpose */
public Foo doSomething(String id, Optional<Bar> barOptional);5. General Programming
Avoid float and double for precise calculations; use BigDecimal for monetary values. Prefer primitive types over boxed types unless required by collections, generics, or reflection.
/** Recommended */
public int sum(int a, int b) { return a + b; }
/** Not recommended */
public Integer sum(Integer a, Integer b) { return a + b; }6. Exceptions
Document every checked exception with Javadoc @throws. Distinguish between client‑side exceptions (invalid requests) and server‑side exceptions (e.g., database timeouts) for proper monitoring.
7. References
Bloch, Joshua. 2018. Effective Java , 3rd Edition.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Alibaba Cloud Developer
Alibaba's official tech channel, featuring all of its technology innovations.
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.
