Clean code in Java
Naming, small methods, avoiding nulls, meaningful exceptions.
Names that reveal intent
Good names make comments unnecessary. d needs a comment; elapsedDays doesn't. Booleans read like questions (isEligibleForRefund), collections are plural (customerEmails). Names like data2 say nothing about what they hold or why the 2 exists.
int d; // elapsed time in days
int elapsedDays;
boolean isEligibleForRefund;
List<String> customerEmails;Small methods, one level
A good method does one thing at one level of abstraction, so it reads like a story. Details live in the small methods it calls, each easy to name, test and review.
void checkout(Cart cart) {
validate(cart);
charge(cart);
sendReceipt(cart);
}Saying "nothing"
List<Order> ordersOf(User u) {
if (u.isNew()) return null;
...
}Every caller needs a null check; one forgotten check is a NullPointerException.
List<Order> ordersOf(User u) {
if (u.isNew()) return List.of();
...
}
Optional<User> findByEmail(String e);An empty list already means "nothing found" and is safe to loop over. For a single value, use Optional.
Optional in action
What does this print?
Optional<String> city = Optional.of("rome");
Optional<String> none = Optional.empty();
String a = city.map(String::toUpperCase)
.orElse("unknown");
String b = none.map(String::toUpperCase)
.orElse("unknown");
System.out.println(a + " " + b);ROME unknownROME nullrome unknownThrows NoSuchElementException
Show the answer
map transforms a present value, so city becomes "ROME". On an empty Optional, map does nothing and orElse supplies the default. No null checks, and the type forces callers to handle "no value".
Swallowed exceptions
An empty catch block turns a failure into silence. The save fails, the caller thinks it worked, and nobody finds out until data is missing. Log it and rethrow, or wrap it in a meaningful exception.
void save(Order o) {
try {
repo.write(o);
} catch (IOException e) {
// ignore
}
}Meaningful exceptions
Throw a specific type with a message that includes the bad value. RuntimeException("error") says nothing. Magic return values like -1 and printed errors are easy to ignore. IllegalArgumentException with details tells the caller exactly what went wrong.
if (amount < 0) {
throw new IllegalArgumentException(
"amount must be >= 0, was " + amount);
}Code that survives review
Code is read far more often than it's written. Reviewers flag cryptic names, 200-line methods, return null for collections and empty catch blocks constantly. Clean code shortens debugging at 3 a.m. because the logs and exceptions tell you what broke.
Key takeaways
- Names reveal intent: elapsedDays, not d
- Small methods at one level of abstraction
- Return empty collections or Optional instead of null
- Throw specific exceptions with useful messages; never swallow them
💡 Good code is like a good street sign: you understand it at a glance, without stopping the car.
Tony Hoare invented the null reference in 1965 for the ALGOL W language. In a 2009 talk he called it his "billion-dollar mistake".
Practice questions
What does this print?
Optional<String> nick = Optional.empty();
String shown = nick.map(String::toUpperCase)
.orElse("guest");
System.out.println(shown);- GUEST
- null
- Throws NoSuchElementException
- guest
Check your answer
guest. map() on an empty Optional does nothing, so orElse supplies the default. No null checks needed.
Three of these names reveal intent. Which is the odd one out?
- elapsedDays
- isEligibleForRefund
- customerEmails
- data2
Check your answer
data2. data2 says nothing about what it holds or why the 2 exists. Good names make comments unnecessary.