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]

类型擦除示例:为什么 ArrayList<Integer> 与 ArrayList<Float> 相等

副标题 / 摘要 Java 泛型在运行时会被擦除,导致不同类型参数的 List 拥有相同 Class。本文解释原因与影响。 目标读者 使用 Java 泛型的开发者 想理解类型系统限制的人 进行 API 设计的工程师 背景 / 动机 Java 泛型是编译期特性。 在运行时,类型参数会被擦除,这会影响反射与类型判断。 核心概念 类型擦除:泛型信息在运行时消失 编译期检查:类型安全主要在编译期保证 运行时类型:只剩原始类型 实践指南 / 步骤 理解泛型只在编译期起作用 避免依赖运行时泛型信息 用显式 Class 参数传递类型 在反射场景保持谨慎 可运行示例 import java.util.ArrayList; public class ErasureDemo { public static void main(String[] args) { ArrayList<Integer> li = new ArrayList<>(); ArrayList<Float> lf = new ArrayList<>(); System.out.println(li.getClass() == lf.getClass()); // true } } 解释与原理 泛型类型参数在编译后被擦除为原始类型(如 ArrayList)。 因此运行时类对象相同。 常见问题与注意事项 这会影响类型安全吗? 编译期仍保证类型安全,但运行时反射可能不安全。 为什么 Java 设计成这样? 为了兼容旧版本与字节码格式。 ...

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

为什么很多工程师不喜欢 Java:现实原因与改进路径

副标题 / 摘要 对 Java 的不满通常来自历史包袱与生态复杂度。本文分析常见原因,并给出现实改进路径。 目标读者 使用 Java 或准备选型的团队 对语言生态有强烈偏好的开发者 关注工程效率的技术负责人 背景 / 动机 Java 有强大的生态与稳定性,但也伴随繁琐与复杂性。 理解抱怨背后的原因,有助于做出理性选择。 核心概念 冗长语法:历史遗留的样板代码 构建复杂:依赖与构建时间增长 运行时成本:GC 与启动时间 实践指南 / 步骤 升级到现代 Java 版本(记录类型、var、模块化) 降低依赖复杂度(收敛生态) 优化构建与启动时间 对关键服务进行性能剖析 可运行示例 // 现代 Java 的 record 减少样板代码 public record User(String id, String name) { public static void main(String[] args) { User u = new User("1", "Alice"); System.out.println(u.name()); } } 解释与原理 对 Java 的“不喜欢”通常来自:历史包袱、复杂生态、构建与运行时成本。 这些问题可以通过现代版本与工程规范改善。 常见问题与注意事项 Java 一定慢吗? 不一定,JIT 在长期运行中很强。 生态复杂是好事还是坏事? 既是优势也是负担。 Java 适合新项目吗? 适合稳定性要求高的企业系统。 ...

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