多级递归中未加访问修饰符的成员变量易致数据交叉污染,必须显式声明为private;禁用package-private字段,杜绝共享可变状态,严禁在递归中使用static变量。

多级递归体系中,成员变量未加可见性修饰(如 private、protected 或 final)极易导致任务间数据交叉污染——尤其在共享对象、复用实例或并发执行场景下。这不是偶发 Bug,而是设计疏漏引发的确定性风险:一个递归分支修改了本该隔离的状态,另一个分支读到的就是“脏值”,且难以复现、日志难追踪。
明确变量作用域边界,禁用默认包级访问
Java 中不写访问修饰符即为 package-private,意味着同包内任意类可直接读写该字段。在递归调用链跨越多个子类或工具类时,极易被意外篡改。
- 所有递归方法依赖的实例变量必须显式声明为 private,禁止裸露字段
- 若需子类扩展逻辑,用 protected final 配合 getter,而非开放可变字段
- 避免在递归入口类中定义“全局中间状态”字段(如
currentPath、resultList),应作为参数传入或封装进不可变上下文对象
递归调用链中杜绝共享可变状态
常见陷阱是把收集结果的容器(如 List、Map)作为类成员,在每次递归前清空再复用。一旦递归并行执行、或被线程池复用,就会出现 A 任务写入的数据被 B 任务读到。
- 每次递归调用都应创建新的局部容器,例如:
List<string> children = new ArrayList();</string>,而非复用this.results - 若性能敏感需复用,必须配合 ThreadLocal 或显式上下文对象(如
RecursionContext),并在递归退出时主动清理 - 绝对不要在递归方法中修改父类或兄弟类持有的共享集合引用
警惕继承链中的隐式变量穿透
当递归逻辑分散在多层继承结构中(如 BaseScanner → DirScanner → ZipScanner),父类定义的 protected 字段可能被各子类无意识覆盖或误读。
- 基类中用于控制流程的字段(如
maxDepth、skipHidden)应设为 private final,通过构造器注入,禁止运行时修改 - 子类若需定制行为,应重写抽象模板方法(如
shouldVisit(File f)),而非直接操作父类状态字段 - 检查所有
super.xxx调用是否隐含对父类可变字段的副作用——例如父类initBuffer()初始化了一个byte[],子类递归中反复Arrays.fill()就会污染其他实例
静态变量在递归中属于高危禁区
静态字段生命周期贯穿整个类加载期,在多级递归+多次调用场景下,等同于跨请求共享状态。首次调用留下的值,第二次调用直接继承,结果必然错乱。
- 递归方法体内禁止使用
static计数器、缓存、配置映射等 - 若真需跨递归层级传递只读配置,用 static final + 不可变对象(如
ImmutableMap) - 已有静态变量参与递归逻辑的,必须在每次顶层调用前手动重置(不推荐),或彻底重构为参数传递模式










