45 Essential Java Coding Practices to Rescue Legacy Code
This article compiles 45 practical Java coding tips—from naming conventions and formatting to exception handling, thread safety, design patterns, and refactoring strategies—aimed at improving readability, maintainability, and performance of existing codebases while preventing common pitfalls.
1. Naming Conventions
Use clear, descriptive names for classes, methods, variables, and parameters. Replace ambiguous names like int i = 0; with meaningful ones such as int count = 0;, and prefer readable English identifiers (e.g., private String idCardNo; → private String idCardNo;).
2. Code Formatting
Adopt consistent spacing, brace alignment, and line length. Modern IDEs can auto‑format code to improve visual comfort.
3. Write Good Comments
Comments should explain intent, describe parameters and return values, warn about constraints, and use // TODO for unfinished work. They supplement code when the logic cannot be expressed clearly.
4. Extract Try‑Catch Logic
Move the core logic inside a try‑catch block to a separate method to keep the main flow readable.
5. Keep Methods Short
A method should do one thing; long methods become hard to understand. Refactor large methods using patterns like Strategy.
6. Remove Duplicate Code
Extract repeated logic into utility classes or common super‑classes to improve extensibility.
7. Use Early Returns
Replace deep nested if statements with early return statements to flatten control flow.
if (!condition1) { return; }
if (!condition2) { return; }
// ...
System.out.println("Result");8. Simplify Complex Conditions
Break complicated boolean expressions into well‑named variables before the final if check.
boolean isBlankOrSpecial = StringUtils.isBlank(name) || "Special".equals(name);
boolean ageOk = age != null && age > 10;
boolean isHan = "汉".equals(national);
if (isBlankOrSpecial && ageOk && isHan) { /* logic */ }9. Elegant Parameter Validation
Leverage Bean Validation annotations such as @NotBlank and @NotNull on DTOs and add @Valid on controller methods.
@Data
public class AddPersonRequest {
@NotBlank(message = "Name cannot be empty")
private String name;
@NotBlank(message = "ID Card cannot be empty")
private String idCardNo;
}10. Unified Return Structure
Standardize API responses with a common wrapper containing code, message, and data fields.
{
"code": 0,
"message": "Success",
"data": "..."
}11. Global Exception Handling
Use Spring’s @ControllerAdvice to avoid repetitive try‑catch blocks across controllers.
12. Avoid Passing Null
Prefer @NonNull and @Nullable annotations to make nullability explicit.
public void updatePerson(@Nullable Person person) {
if (person == null) { return; }
personService.updateById(person);
}13. Avoid Returning Null
Return Optional instead of null for potentially absent values.
public Optional<Person> getPersonById(Long id) {
return Optional.ofNullable(personService.selectById(id));
}14. Logging Standards
Make logs searchable with clear keywords.
Log stack traces for errors.
Use appropriate log levels (error, info).
Avoid logging huge payloads like Base64 images.
15. Consistent Library Usage
Choose a single JSON library (e.g., Jackson) and avoid mixing multiple libraries.
16. Prefer Utility Classes
Use collection utilities (e.g., CollectionUtils.isEmpty()) instead of manual checks.
17. Extract Magic Numbers
Replace literal constants with named constants for readability.
private static final String GUANG_DONG = "广东省";
if (GUANG_DONG.equals(province)) { System.out.println("靓仔~~"); }18. Release Resources in finally
Always release locks or I/O resources inside a finally block.
19. Use Thread Pools
Replace manual thread creation with ExecutorService to reuse threads and control concurrency.
20. Name Threads
Assign meaningful names to threads to simplify debugging.
21. Use volatile for Visibility
Mark shared flags with volatile to guarantee visibility across threads.
22. Reduce Lock Scope
Only lock the critical section; keep non‑critical code outside the lock.
23. Define Enums for Types
Use enums instead of magic numbers to represent distinct categories.
24. Set Timeouts on Remote Calls
Configure timeouts for RPC or HTTP calls to avoid indefinite blocking.
25. Pre‑size Collections
Specify initial capacity for ArrayList and HashMap to reduce resizing overhead.
26. Avoid BeanUtils for Copying
Prefer compile‑time mappers like MapStruct over reflection‑based BeanUtils for better performance.
27. Use StringBuilder for Concatenation
When building strings in loops, use a single StringBuilder instead of the + operator.
StringBuilder sb = new StringBuilder();
String result = sb.append("123").append("456").append("789").toString();28. Specify Rollback Exceptions
Annotate @Transactional with rollbackFor to include checked exceptions.
29. Beware of Self‑Invocation
Calling a proxied method from within the same class bypasses AOP; inject the proxy instead.
30. Select Required Fields
Query only needed columns to reduce network traffic and enable index‑only scans.
Wrappers.query().select("name");31. Avoid DB Calls Inside Loops
Batch fetch data and map results instead of issuing a query per iteration.
32. Prefer Aggregation Over Inheritance
Use composition or aggregation to reduce coupling and improve flexibility.
public class OrderService {
private UserService userService = new UserService(); // composition
}33. Apply Design Patterns Wisely
Introduce patterns like Strategy when they solve a real problem; avoid over‑engineering.
public interface MessageNotifier { boolean support(int type); void notify(User u, String c); }34. Interface‑Based Programming
Program to abstractions (interfaces) rather than concrete implementations for easier swapping.
35. Regular Refactoring
Continuously improve legacy code as business requirements evolve.
36. Null‑Check Discipline
Guard against NPEs by explicit null checks or using Optional.
37. Override toString in POJOs
Provide meaningful toString() implementations for debugging.
38. Use Constants for Magic Values
Replace hard‑coded literals with well‑named constants.
39. Thread‑Safe Collections
Choose concurrent collections (e.g., CopyOnWriteArrayList) when multiple threads access shared data.
40. Double‑Check Locking for Tokens
When caching tokens, use double‑check to prevent race conditions.
41. Reduce Lock Contention
Minimize the code inside synchronized blocks to improve throughput.
42. Avoid Unnecessary Asynchrony
Only use async execution when transaction integrity and CPU load are acceptable.
43. Use Enums for Fixed Types
Define enums for fixed categories such as attachment types.
44. Install Code Quality Plugins
Use tools like Alibaba Java Coding Guidelines plugin to enforce standards.
45. Communicate with Team
Discuss design decisions and seek peer reviews to avoid isolated mistakes.
References
Clean Code
Alibaba Java Development Manual
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.
Sanyou's Java Diary
Passionate about technology, though not great at solving problems; eager to share, never tire of learning!
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.
