有没有 'proper' 方法可以避免 'must be final' 错误?

Is there a 'proper' way to avoid 'must be final' error?

我想写一个这样的循环:

ArrayList<Thread> threads = new ArrayList<>();
for(int i = 0; i < THREADS_TOTAL; i++) {
    threads.add(new Thread() {
        @Override
        public void run(){
            foo(i);
        }
    });
    // more code
}

但我收到编译器错误

Local variable i defined in an enclosing scope must be final or effectively final.

有没有办法避免这个错误,特别是当有问题的变量是原始类型时,匿名 class 应该看不到更改?我考虑过的选项是:

  1. 在循环外定义一个命名的 class 并将 i 传递给构造函数。我不喜欢这个选项,因为它会产生不必要的间接访问,而且这是在创建单元测试的上下文中,所以我最终会得到很多额外的内部 classes,每个这样的情况一个。
  2. 使用 IntStream、forEach 和 lambda。由于 // more code.
  3. ,这并不适用
  4. 创建另一个变量,例如在循环内使用 int j = i; 并在匿名 class 内使用 j。这似乎是迄今为止最多 'clean' 的选项,但我仍然不喜欢它,因为这一行没有语义目的,它只是为了安抚编译器。

最直接的 IMO 是:

ArrayList<Thread> threads = new ArrayList<>();
for(int i = 0; i < THREADS_TOTAL; i++) {
    final int good_name = i;
    threads.add(new Thread(() -> foo(good_name)));
    // more code
}

简明扼要。