用成员内部类实现父子级联菜单,核心是利用内部类天然持有的外部类引用,让子菜单能直接访问父菜单的数据和方法,结构清晰、耦合低、语义明确。

用成员内部类建模菜单层级关系
成员内部类(非静态)默认持有对外部类实例的隐式引用,非常适合表达“子属于父”的树形结构。比如外部类 Menu 表示一个菜单项,其成员内部类 Submenu 表示它的子菜单,自然继承父菜单的 ID、权限、点击行为等上下文。
- 外部类
Menu存储一级菜单信息(如 name、url、order) - 内部类
Submenu可直接调用Menu.this.getName()获取父名,无需额外传参 - 每个
Submenu实例都绑定到唯一的Menu实例,逻辑上就是“这个子项属于这个父项”
支持多层嵌套:内部类里再定义内部类
Java 允许在内部类中继续定义成员内部类,可自然延伸为三级甚至更深菜单。例如:Menu → Submenu → SubSubmenu,每一层都持有上一层的引用。
-
Submenu中定义SubSubmenu,它可通过Submenu.this.getMenu().getName()向上跨两级访问根菜单名 - 避免用 List<Object> 或泛型嵌套带来的类型模糊,每层职责明确、IDE 可提示、编译期可校验
- 添加子项时直接 new 内部类实例,如
menu.new Submenu("设置", "/setting"),语义直白
统一管理与遍历:在外部类中封装树操作
把构建、查找、渲染等通用逻辑放在外部类中,利用内部类的访问权限简化实现。内部类可自由访问外部类的 private 字段,外部类也能直接访问内部类的 package-private 成员。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 在
Menu中维护private List<Submenu> submenus,提供addSubmenu(...)方法 - 实现
toTreeJson()方法递归调用Submenu.toTreeJson(),自动拼接父子路径 - 查找某 URL 对应的完整路径时,
Menu可委托给各层内部类分治处理,无需暴露内部结构
注意生命周期与序列化问题
成员内部类实例强引用外部类实例,若菜单数据需持久化或跨线程传递,要小心内存泄漏或序列化失败。
立即学习“Java免费学习笔记(深入)”;
- 避免将内部类实例长期缓存(如放进静态 Map),否则会阻止外部类被回收
- 若需 JSON 序列化,推荐用 Jackson 的
@JsonUnwrapped或自定义序列化器,而不是直接序列化内部类对象 - 必要时改用静态内部类 + 显式传入 parent 引用,牺牲一点语法糖换取可控性

















