有没有 '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 应该看不到更改?我考虑过的选项是:
- 在循环外定义一个命名的 class 并将
i
传递给构造函数。我不喜欢这个选项,因为它会产生不必要的间接访问,而且这是在创建单元测试的上下文中,所以我最终会得到很多额外的内部 classes,每个这样的情况一个。
- 使用 IntStream、forEach 和 lambda。由于
// more code
. ,这并不适用
- 创建另一个变量,例如在循环内使用
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
}
简明扼要。
我想写一个这样的循环:
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 应该看不到更改?我考虑过的选项是:
- 在循环外定义一个命名的 class 并将
i
传递给构造函数。我不喜欢这个选项,因为它会产生不必要的间接访问,而且这是在创建单元测试的上下文中,所以我最终会得到很多额外的内部 classes,每个这样的情况一个。 - 使用 IntStream、forEach 和 lambda。由于
// more code
. ,这并不适用
- 创建另一个变量,例如在循环内使用
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
}
简明扼要。