16 Essential Java Coding Habits Every Developer Should Master
This article compiles sixteen classic Java coding habits—from self‑testing changes and validating method parameters to handling resources, avoiding runtime errors, and ensuring thread‑safety and cache consistency—providing practical guidance that helps prevent most non‑business bugs.
1. Self‑test after code changes
Run tests after any code modification, even a single variable or configuration line, to catch regressions early.
2. Validate method parameters
Check that inputs are not null and meet length or format expectations; unvalidated parameters often cause low‑level bugs such as database insert errors.
If a varchar(16) column receives a 32‑character string without validation, the insert will throw an exception.
3. Preserve compatibility when modifying old interfaces
When extending an existing public API, maintain backward compatibility to avoid deployment failures. For example, add a new parameter to a Dubbo interface while keeping the old signature functional.
void oldService(A, B) { newService(A, B, null); }
void newService(A, B, C);4. Add clear comments for complex business logic
While good naming reduces the need for comments, intricate business code should be accompanied by concise explanations to aid future maintenance.
5. Close I/O streams
Unclosed streams waste system resources; always close them in a finally block or use try‑with‑resources (Java 7+).
FileInputStream fdIn = null;
try {
fdIn = new FileInputStream(new File("/jay.txt"));
} catch (FileNotFoundException e) {
log.error(e);
} catch (IOException e) {
log.error(e);
} finally {
try { if (fdIn != null) fdIn.close(); } catch (IOException e) { log.error(e); }
} try (FileInputStream inputStream = new FileInputStream(new File("jay.txt"))) {
// use resources
} catch (FileNotFoundException e) {
log.error(e);
} catch (IOException e) {
log.error(e);
}6. Guard against runtime errors
Check collection size before accessing elements and avoid division by zero or null dereferences.
if (CollectionsUtil.isNotEmpty(list) && list.size() > 1) {
String name = list.get(1).getName();
}7. Batch remote or database calls
Avoid making remote or DB calls inside loops; retrieve data in bulk (e.g., 500 records per batch).
remoteBatchQuery(param); for (int i = 0; i < n; i++) {
remoteSingleQuery(param);
}8. Consider concurrency for read‑modify‑write
Operations that read a record then update it are not atomic; under multithreading they can cause lost updates. Use atomic DB operations (e.g., delete‑if‑exists) to ensure consistency.
if (deleteAvailableTicketById(ticketId) == 1) {
// add cash
} else {
return "No available coupon";
}Thread A adds cash
Thread B adds cash
Thread A deletes ticket flag
Thread B deletes ticket flag
9. Null‑check before accessing object properties
Always verify an object is not null before calling its methods to avoid NullPointerException.
if (object != null) {
String name = object.getName();
}10. Use appropriate thread pools instead of creating raw threads
Thread pools reduce creation overhead, improve response time, and enable resource reuse. Separate critical business workloads into isolated pools with suitable configurations.
Manage threads efficiently
Improve latency
Reuse resources
11. Run hand‑written SQL in the database and check the execution plan
Executing SQL manually helps catch syntax errors and allows you to use EXPLAIN to verify index usage.
explain select * from user where userid = 10086 or age = 18;12. Handle third‑party API calls with retries, timeouts, and security
When invoking external services, configure connection timeouts, retry counts, and, for sensitive operations like payments, add signature verification and encryption.
Example: set connect‑time and retry attempts for an HTTP request.
13. Design idempotent interfaces
Idempotent APIs produce the same effect regardless of how many times they are called, preventing duplicate processing in scenarios like rapid user clicks.
Query operations
Unique indexes
Token mechanisms
Database delete
Optimistic / pessimistic locks
Distributed locks (Redis, Zookeeper)
State‑machine based idempotency
14. Ensure linear safety in high‑concurrency scenarios
Standard collections like HashMap are not thread‑safe; replace them with ConcurrentHashMap or other concurrent structures under heavy load.
HashMap, ArrayList, LinkedList, TreeMap – not thread‑safe Vector, Hashtable, ConcurrentHashMap – thread‑safe
15. Consider master‑slave replication lag
Writes go to the master while reads may hit a lagging replica; for critical data, force reads from the master or redesign to tolerate eventual consistency.
16. Cache consistency and protection against cache pitfalls
Cache usage speeds up reads but requires careful handling of consistency, cache penetration, cache avalanche, and cache breakdown.
Cache avalanche: massive expiration causing DB overload. Cache penetration: repeated DB hits for non‑existent keys. Cache breakdown: hot key expires, leading to a surge of DB requests.
Git repository: https://github.com/whx123/JavaHome
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.
ITPUB
Official ITPUB account sharing technical insights, community news, and exciting events.
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.
