Java 栈的内存泄漏:为什么 pop 之后仍然占用

副标题 / 摘要 Java 有 GC 也会出现内存泄漏。本文用经典栈实现解释为什么对象引用没清理会导致泄漏。 目标读者 使用 Java 的开发者 关注内存问题的工程师 需要理解引用机制的人 背景 / 动机 GC 只能回收“不可达对象”。 如果引用没清理,哪怕对象不再需要,也不会被回收。 核心概念 对象可达性:决定是否可回收 引用残留:对象仍被数组引用 逻辑泄漏:对象不再使用却无法回收 实践指南 / 步骤 识别不再使用的引用 在 pop 后显式置空 使用工具分析堆快照 写回归测试验证 可运行示例 import java.util.EmptyStackException; import java.util.Arrays; public class Stack { private Object[] elements; private int size = 0; private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack() { elements = new Object[DEFAULT_INITIAL_CAPACITY]; } public void push(Object e) { ensureCapacity(); elements[size++] = e; } public Object pop() { if (size == 0) throw new EmptyStackException(); Object result = elements[--size]; elements[size] = null; // 防止内存泄漏 return result; } private void ensureCapacity() { if (elements.length == size) elements = Arrays.copyOf(elements, 2 * size + 1); } } 解释与原理 数组中残留的引用使对象仍然“可达”。 显式置空可以让 GC 回收对象。 ...

2026年1月24日 · 1 分钟 · map[name:Jeanphilo]

如何重构嵌套错误码:从深层 if 到清晰流程

副标题 / 摘要 深层嵌套的错误处理难以维护。本文用“早返回 + 分解函数”重构嵌套代码。 目标读者 参与代码评审的工程师 需要重构遗留代码的团队 关注可维护性的开发者 背景 / 动机 嵌套 if 会让控制流难以理解。 重构的目标是降低认知负担并明确失败路径。 核心概念 早返回:失败立刻返回 错误码表意:减少嵌套层级 小函数拆分:让逻辑更清晰 实践指南 / 步骤 把失败路径提前返回 给错误码赋予清晰语义 把每一步拆成小函数 用测试覆盖边界 可运行示例 #include <stdbool.h> int op1(); int op2(); int op3(); int run() { int err = op1(); if (err) return err; err = op2(); if (err) return err; err = op3(); if (err) return err; return 0; } 解释与原理 早返回让失败路径清晰,避免“右倾树式嵌套”。 拆分函数还能让每个步骤可独立测试。 常见问题与注意事项 早返回会不会隐藏逻辑? 不会,它让逻辑更直接。 是否需要统一错误码? 需要,否则调试困难。 如何保证重构安全? 用测试验证行为一致。 最佳实践与建议 先写测试再重构 用枚举/常量替代魔法数字 让错误码具备可读语义 小结 / 结论 重构嵌套错误处理的关键是“减少层级、明确失败路径”。 早返回能显著提升可读性。 ...

2026年1月24日 · 1 分钟 · map[name:Jeanphilo]

什么样的代码可读性强:结构、命名与认知负担

副标题 / 摘要 可读性强的代码不一定短,但必须降低认知负担。本文给出可执行的判断标准。 目标读者 参与代码评审的工程师 关注可维护性的团队 初中级开发者 背景 / 动机 代码的主要读者是人而不是机器。 可读性差会带来维护成本和错误风险。 核心概念 结构清晰:层次分明、职责单一 命名准确:表达意图而非实现细节 认知负担:阅读时需要记住的临时信息 实践指南 / 步骤 函数短小且单一职责 命名体现意图而不是过程 减少嵌套,提前返回 用测试与注释解释复杂逻辑 可运行示例 # 不好的命名 def f(x): return x * 1.08 # 更好的命名 def apply_tax(price): return price * 1.08 if __name__ == "__main__": print(apply_tax(100)) 解释与原理 读代码的时间通常远大于写代码。 清晰命名与结构能降低理解成本,减少错误。 常见问题与注意事项 注释能替代好命名吗? 不能,注释是补充而不是替代。 缩短代码一定更好? 不一定,过度压缩会降低可读性。 如何量化可读性? 用评审与维护时间做间接衡量。 最佳实践与建议 在评审中强调命名与结构 复杂逻辑写成小函数 用一致的代码风格 小结 / 结论 可读性强的代码能降低认知负担,减少维护成本。 结构、命名与测试是三大关键。 参考与延伸阅读 Clean Code Code Complete 元信息 阅读时长:6~8 分钟 标签:可读性、代码质量 SEO 关键词:可读性, 命名 元描述:定义什么是可读性强的代码。 行动号召(CTA) 挑一段难读的代码,重命名并拆分后再做一次评审。

2026年1月24日 · 1 分钟 · map[name:Jeanphilo]

重构何时有用:时机、信号与风险控制

副标题 / 摘要 重构不是“重写”,而是持续改善代码结构。本文给出重构适用场景、触发信号与控制风险的方法。 目标读者 需要维护遗留系统的工程师 负责技术债管理的团队 关注代码质量的开发者 背景 / 动机 不重构,技术债会持续累积;盲目重构,又可能影响交付。 理解“何时重构”比“怎么重构”更重要。 核心概念 技术债:当前效率换取未来成本 重构:不改变外部行为的结构改进 触发信号:重复代码、复杂度上升、修改成本高 实践指南 / 步骤 识别高频修改区域 先补齐测试 小步重构,持续验证 避免大规模“重写” 把重构与业务迭代结合 可运行示例 # 重构前 def calc_total(items): total = 0 for name, price in items: if price > 0: total += price return total # 重构后 def calc_total(items): return sum(price for _, price in items if price > 0) 解释与原理 重构的价值在于降低未来修改成本。 如果一个模块频繁修改且修改困难,就应该优先重构。 常见问题与注意事项 重构是不是浪费时间? 如果能降低长期成本,就不是浪费。 什么时候不该重构? 即将下线的模块不值得投入。 如何控制风险? 小步重构 + 测试覆盖。 最佳实践与建议 把重构纳入日常开发 优先处理“高频痛点”模块 用指标评估重构收益 小结 / 结论 重构适合在“高频修改、高复杂度”的模块中进行。 控制风险的关键是测试与小步迭代。 ...

2026年1月24日 · 1 分钟 · map[name:Jeanphilo]

什么是好代码:可读、可测、可演进

副标题 / 摘要 好代码不是“聪明”,而是“可理解、可验证、可演进”。本文给出工程视角的判断标准与实践方法。 目标读者 想提升代码质量的工程师 负责代码评审的团队 需要建立编码规范的技术负责人 背景 / 动机 代码质量决定维护成本与交付速度。 在多人协作中,好代码比“聪明代码”更重要。 核心概念 可读性:降低理解成本 可测试性:能被自动验证 可演进性:便于修改与扩展 实践指南 / 步骤 写清晰命名与结构 保持函数短小、职责单一 用测试锁定核心逻辑 减少隐式依赖与副作用 可运行示例 # 不好:命名与职责不清晰 def f(x): if x > 0: return x * 1.08 return x # 更好:意图清晰 def apply_tax(price): if price <= 0: return price return price * 1.08 if __name__ == "__main__": print(apply_tax(100)) 解释与原理 好代码的价值不在于“技巧”,而在于团队可以快速理解与修改。 可读性、可测试性与可演进性是关键指标。 常见问题与注意事项 短代码一定更好吗? 不一定,重要的是表达清晰。 注释能替代可读性吗? 不能,注释应补充而不是替代。 可测试性为什么重要? 它是安全改动的基础。 最佳实践与建议 代码评审关注意图表达 建立清晰的命名规范 把复杂逻辑拆成小函数 小结 / 结论 好代码让团队更快、更稳地交付。 可读、可测、可演进是长期价值的核心。 ...

2026年1月24日 · 1 分钟 · map[name:Jeanphilo]