首先,您显然只想初始化一次。递归中的一个常见模式是:
public void run(int opt) {
run_helper(opt, 0);
}
private void run(int opt, int depth) {
if (whatever) { run(opt, depth + 1); }
}
外部方法只做一些初始化。
您会经常看到建议的“解决方案”(例如,在对您问题的第一条评论中)将使用静态变量。这种方法是一种糟糕的风格,一旦添加多线程(例如,通过制作 UI 版本,或在多线程 Web 服务器中运行它),将导致您的程序以各种奇怪的方式失败。最糟糕的是,它可能一开始似乎可以工作,并且只有在有很多用户时才开始巧妙地行为不端。 因此,除了常量之外的所有内容都远离“静态”!
对于“静态”,它通常看起来像这样:
static int counter;
public void start() {
counter = 0;
recurse();
}
public void recurse() {
counter += 1;
if (whatever) { recurse(); }
}
现在假设两个用户同时调用start。 他们将覆盖彼此的计数器!因为静态意味着它在线程和用户之间共享。
这是一个非常容易理解的解决方案:
class MyTask {
int counter = 0;
public void recurse() {
counter++;
if (whatever) { recurse(); }
}
public int getIterations() {
return counter;
}
}
public void run() {
MyTask task = new MyTask();
task.run();
System.out.println("Task took "+task.getIterations()+" itertions.");
}
然后您创建一个任务,运行它,并在最后检索计数器。干净、简单、高效、可靠。 如果你有多个线程/用户,每个都有一个单独的 MyTask 对象,你不会遇到任何问题。
另外,您可以添加额外的统计信息,它们都干净地包装在任务对象中。 “每次迭代的平均时间”? “平均递归深度”?没问题。任务对象也可以用来存储你的结果。
这里建议使用ThreadLocal。我不同意这一点。它根本没有提供任务对象的任何好处。只需尝试使用ThreadLocal 和任务对象来实现它,您就会看到不同之处。另外,ThreadLocal 在经验上比访问堆值慢 10 倍(参见https://stackoverflow.com/a/4756605/1060350)。对于int,情况可能更糟。所以永远不要在性能关键的代码路径中调用ThreadLocal#get。如果您打算使用ThreadLocal,请在此代码路径之外使用它,并使用局部变量(或任务对象)将“局部静态”变量提供给您的关键代码路径。