16. 尽量使用单例模式避免重复对象创建
// 错误示范:
public class ExpensiveObject {public ExpensiveObject() {// 每次都创建新对象}
}// 正确示范:
public class ExpensiveObject {private static final ExpensiveObject INSTANCE = new ExpensiveObject();private ExpensiveObject() {// 私有构造函数,防止外部实例化}public static ExpensiveObject getInstance() {return INSTANCE;}
}
解释: 对于创建成本高的对象,可以通过单例模式确保只创建一个实例,避免资源浪费。
17. 优先使用不可变对象
// 错误示范:
public class MutablePoint {public int x;public int y;
}// 正确示范:
public class ImmutablePoint {private final int x;private final int y;public ImmutablePoint(int x, int y) {this.x = x;this.y = y;}public int getX() { return x; }public int getY() { return y; }
}
解释: 不可变对象天生是线程安全的,且能够减少不必要的状态变更。
18. 使用批量操作减少I/O
// 错误示范:
BufferedReader reader = new BufferedReader(new FileReader("file.txt"));
String line;
while ((line = reader.readLine()) != null) {process(line); // 逐行处理,I/O频繁
}// 正确示范:
BufferedReader reader = new BufferedReader(new FileReader("file.txt"));
StringBuilder content = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {content.append(line); // 批量读取
}
process(content.toString());
解释: I/O操作非常耗时,尽量减少I/O调用次数,提高性能。
19. 合理使用线程池
// 错误示范:
Thread thread = new Thread(() -> doTask());
thread.start(); // 每次任务创建新线程// 正确示范:
ExecutorService executor = Executors.newFixedThreadPool(10);
executor.submit(() -> doTask()); // 使用线程池复用线程
解释: 线程池能够有效管理线程资源,避免频繁创建和销毁线程带来的性能开销。
20. 使用java.util.Optional代替null检查
// 错误示范:
if (object != null) {process(object);
}// 正确示范:
Optional<Object> optional = Optional.ofNullable(object);
optional.ifPresent(this::process); // 优雅处理可能为空的对象
解释: Optional
能够更优雅地处理null
值,减少空指针异常,并提高代码的可读性。
21. 避免同步整个方法
// 错误示范:
public synchronized void increment() {counter++; // 整个方法都被同步,效率低下
}// 正确示范:
public void increment() {synchronized(this) {counter++; // 只同步必要的部分}
}
解释: 仅同步关键部分可以减少锁的持有时间,提升并发性能。
22. 避免在循环中使用try-catch
// 错误示范:
for (int i = 0; i < list.size(); i++) {try {process(list.get(i));} catch (Exception e) {e.printStackTrace(); // 每次循环都会捕获异常,开销大}
}// 正确示范:
try {for (int i = 0; i < list.size(); i++) {process(list.get(i));}
} catch (Exception e) {e.printStackTrace(); // 将try-catch移到外层
}
解释: 异常处理的开销很大,应尽量避免在循环中反复捕获异常。
23. 使用并行流处理大数据
// 错误示范:
list.stream().forEach(item -> process(item)); // 顺序流处理// 正确示范:
list.parallelStream().forEach(item -> process(item)); // 并行流处理
解释: 对于大数据集,可以利用并行流来充分发挥多核CPU的性能。
24. 优先使用延迟加载(Lazy Initialization)
// 错误示范:
public class Config {private HeavyObject heavyObject = new HeavyObject(); // 对象在类加载时即创建public HeavyObject getHeavyObject() {return heavyObject;}
}// 正确示范:
public class Config {private HeavyObject heavyObject;public HeavyObject getHeavyObject() {if (heavyObject == null) {heavyObject = new HeavyObject(); // 延迟加载,仅在使用时创建}return heavyObject;}
}
解释: 延迟加载能够优化内存占用,尤其是当对象创建成本高且不一定总会被使用时。
25. 使用volatile
关键字保证可见性
// 错误示范:
private boolean flag = false;public void setFlag() {flag = true;
}public boolean isFlag() {return flag; // 在多线程中,可能无法及时看到flag的变化
}// 正确示范:
private volatile boolean flag = false;public void setFlag() {flag = true;
}public boolean isFlag() {return flag; // 使用volatile保证线程之间的可见性
}
解释: volatile
可以确保变量在线程间的可见性,避免脏数据问题。
26. 避免使用System.out.println()
进行日志输出
// 错误示范:
System.out.println("Debugging info"); // 控制台输出,性能低下// 正确示范:
Logger logger = Logger.getLogger(Example.class.getName());
logger.info("Debugging info"); // 使用日志框架,有效管理日志输出
解释: System.out.println()
性能较低,且缺乏日志级别控制,应使用专业的日志框架。
27. 使用Objects.equals
来比较对象
// 错误示范:
if (a != null && a.equals(b)) { // 手动null检查// 正确示范:
if (Objects.equals(a, b)) { // 使用Objects.equals(),避免null检查
}
解释: Objects.equals()
可以简化对象比较,避免空指针异常。
28. 使用局部变量替代全局变量
// 错误示范:
public class Example {private int result; // 使用全局变量,可能引发线程安全问题public void process() {result = calculate();}
}// 正确示范:
public class Example {public void process() {int result = calculate(); // 使用局部变量,避免线程安全问题}
}
解释: 局部变量作用域小,生命周期短,有利于GC优化和线程安全。
29. 合理利用缓存
// 错误示范:
public int calculate(int input) {return complexCalculation(input); // 每次调用都重新计算
}// 正确示范:
private Map<Integer, Integer> cache = new HashMap<>();public int calculate(int input) {return cache.computeIfAbsent(input, this::complexCalculation); // 使用缓存存储计算结果
}
解释: 对于高开销的计算,使用缓存可以避免重复计算。
30. 使用CompletableFuture
进行异步编程
// 错误示范:
Thread thread = new Thread(() -> process());
thread.start(); // 手动创建线程进行异步处理// 正确示范:
CompletableFuture.runAsync(() -> process()); // 使用CompletableFuture进行异步处理
解释: CompletableFuture
简化了异步编程,并提供了丰富的功能进行任务组合和处理。
通过本文展示的30个优化技巧,开发者可以大幅提高Java程序的运行效率,从而实现更快的执行速度、更少的资源消耗和更低的维护成本。这些技巧涵盖了常见的开发场景,包括集合处理、字符串操作、并发编程、I/O优化等方面。掌握并灵活运用这些技巧,可以使得代码不仅更加健壮,还能应对复杂的生产环境中的性能挑战。在日常开发中,持续关注代码的性能和优化,才能编写出高效、稳定且易于扩展的Java应用。