Java Code Optimization Best Practices and Performance Tips
This article presents a comprehensive collection of Java code‑optimization techniques—ranging from using final modifiers and reusing objects to proper resource handling, efficient collection sizing, avoiding reflection, and leveraging low‑level operations—aimed at reducing binary size, improving runtime efficiency, and preventing hard‑to‑detect bugs in production systems.
Code optimization is essential for preventing unknown runtime errors, reducing downtime caused by lengthy deployments, and lowering long‑term maintenance effort.
The primary goals are to shrink the code footprint and boost execution speed.
1. Use final on classes and methods – enables the JVM to inline calls, improving performance by up to 50%.
2. Reuse objects – prefer StringBuilder / StringBuffer over string concatenation to avoid excessive object creation and garbage collection.
3. Prefer local variables – stack‑allocated variables are faster than heap‑allocated static or instance fields.
4. Close streams promptly – releasing I/O resources prevents large overhead and potential failures.
5. Avoid repeated calculations – cache results such as list.size() before loops.
for (int i = 0, length = list.size(); i < length; i++) {
// ...
}6. Apply lazy loading – instantiate objects only when needed.
if (i == 1) {
String str = "aaa";
list.add(str);
}7. Use exceptions sparingly – creating a Throwable incurs stack‑trace generation overhead.
8. Avoid try…catch inside loops – place the block at the outermost level.
9. Pre‑size collections – for ArrayList, StringBuilder, etc., specify an initial capacity to reduce resizing costs.
StringBuilder sb = new StringBuilder(5000); // avoid default 16‑char growth10. Use System.arraycopy() for bulk copies .
11. Replace arithmetic with bit shifts when possible – shifts are faster than multiplication/division.
a = val << 3; // val * 8
b = val >> 1; // val / 212. Avoid creating objects inside loops – reuse a single reference.
Object obj = null;
for (int i = 0; i <= count; i++) {
obj = new Object();
}13. Prefer arrays over ArrayList when size is known .
14. Favor HashMap , ArrayList , StringBuilder over synchronized alternatives unless thread safety is required.
15. Do not declare public static final arrays – the reference can be modified, creating a security risk.
16. Use singletons judiciously – suitable for resource control, instance limiting, and shared data.
17. Minimize static variables – they stay in memory for the lifetime of the class.
18. Invalidate unused HTTP sessions to free server memory.
19. Iterate ArrayList with index loops, not foreach, for better RandomAccess performance .
if (list instanceof RandomAccess) {
for (int i = 0; i < list.size(); i++) { /* ... */ }
} else {
Iterator<?> it = list.iterator();
while (it.hasNext()) { it.next(); }
}20. Prefer synchronized blocks over synchronized methods to limit the locked scope.
21. Declare constants as static final with uppercase names for compile‑time inlining.
22. Remove unused variables and imports to keep code clean.
23. Avoid reflection in hot paths – it is slower and can be replaced by direct calls.
24. Use connection pools and thread pools to reuse expensive resources.
25. Use buffered I/O streams for higher throughput.
26. Choose ArrayList for frequent random access and LinkedList for many insertions/removals .
27. Limit the number of method parameters – typically 3‑4; wrap many fields in a DTO.
28. Write constant first in equals checks to avoid NullPointerException. if ("123".equals(str)) { /* ... */ } 29. Prefer if (i == 1) over if (1 == i) for readability in Java .
30. Do not call toString() on arrays – it yields a hash code string; use Arrays.toString() instead.
31. Avoid unsafe down‑casting of primitive types – it truncates data.
32. Remove unused elements from shared collections to prevent memory leaks.
33. Convert primitives to strings using toString() or String.valueOf() (fastest) rather than concatenation . String s = Integer.toString(i); // fastest 34. Iterate Map efficiently using entrySet() and an iterator .
Iterator<Map.Entry<String,String>> iter = hm.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<String,String> e = iter.next();
System.out.println(e.getKey() + "\t" + e.getValue());
}35. Close resources in separate try‑catch blocks to guarantee each close executes.
36. Remove ThreadLocal after use to avoid leaking data across pooled threads.
37. Replace magic numbers with named constants for readability.
38. Use uppercase L for long literals to avoid confusion with digit 1.
39. Annotate overridden methods with @Override to catch signature mismatches.
40. Prefer Objects.equals(a,b) over a.equals(b) to avoid NPEs .
41. Use StringBuilder for repeated string concatenation inside loops .
42. Do not catch unchecked exceptions unless you can handle them .
43. Use ThreadLocalRandom instead of shared Random in multithreaded code .
44. Make constructors of utility, singleton, and factory classes private to prevent unwanted instantiation.
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.
Code Ape Tech Column
Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn
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.
