Effective Java Checklist

Code Review Checklist

AreaGood practice
Null handlingreturn empty collections and Optional, not null; Objects.requireNonNull on inputs
Exceptionsnever swallow (catch (Exception e) {}); throw specific exceptions with context; do not use exceptions for flow control
MoneyBigDecimal (or long paise), never double
Equalityoverride equals and hashCode together, or use records
Classesfavour composition over inheritance; minimize mutability and visibility
Interfacesprogram to interfaces: List<Order> orders = new ArrayList<>()
Enumsuse enums instead of int/String constants
LoggingSLF4J with placeholders log.info("Order {} placed", id); never log passwords, card numbers, OTPs
Resourcestry-with-resources for everything AutoCloseable
Datesjava.time (Instant, LocalDate, ZonedDateTime), not Date/Calendar

Why BigDecimal for Money

Example

import java.math.*;

public class Main {
    public static void main(String[] args) {
        double d = 0.1 + 0.2;
        System.out.println("double: 0.1 + 0.2 = " + d);

        BigDecimal b = new BigDecimal("0.1").add(new BigDecimal("0.2"));
        System.out.println("BigDecimal: 0.1 + 0.2 = " + b);

        BigDecimal price = new BigDecimal("999.99");
        BigDecimal gst = price.multiply(new BigDecimal("0.18")).setScale(2, RoundingMode.HALF_UP);
        System.out.println("GST on 999.99 = " + gst + ", total = " + price.add(gst));

        System.out.println("new BigDecimal(0.1) = " + new BigDecimal(0.1).toString().substring(0, 22) + "...");
        System.out.println("compareTo vs equals: " + (new BigDecimal("2.0").compareTo(new BigDecimal("2.00")) == 0)
                + " / " + new BigDecimal("2.0").equals(new BigDecimal("2.00")));
    }
}

Output

double: 0.1 + 0.2 = 0.30000000000000004
BigDecimal: 0.1 + 0.2 = 0.3
GST on 999.99 = 180.00, total = 1179.99
new BigDecimal(0.1) = 0.10000000000000000555...
compareTo vs equals: true / false

Tip: Create BigDecimal from a String (new BigDecimal("0.1")) or BigDecimal.valueOf(0.1), never new BigDecimal(0.1). Compare with compareTo, because equals also compares the scale.

Practice

Exercise: What is wrong with this code? try { process(order); } catch (Exception e) { }

Show answer
// The exception is swallowed: the order silently fails and nobody knows why.
// Catch what you can handle, log with context, and rethrow or return a clear result:
try {
    process(order);
} catch (PaymentException e) {
    log.warn("Payment failed for order {}", order.id(), e);
    order.markPaymentPending();
}